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:
parent
3d5998cd63
commit
804f5a94d5
|
|
@ -2148,8 +2148,8 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
|
||||||
return max(tru_wid,fal_wid);
|
return max(tru_wid,fal_wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_ternary_operand_compat(ivl_variable_type_t l,
|
bool NetETernary::test_operand_compat(ivl_variable_type_t l,
|
||||||
ivl_variable_type_t r)
|
ivl_variable_type_t r)
|
||||||
{
|
{
|
||||||
if (l == IVL_VT_LOGIC && r == IVL_VT_BOOL)
|
if (l == IVL_VT_LOGIC && r == IVL_VT_BOOL)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2245,7 +2245,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return 0;
|
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 "
|
cerr << get_fileline() << ": error: Data types "
|
||||||
<< tru->expr_type() << " and "
|
<< tru->expr_type() << " and "
|
||||||
<< fal->expr_type() << " of ternary"
|
<< fal->expr_type() << " of ternary"
|
||||||
|
|
|
||||||
|
|
@ -746,7 +746,7 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
|
||||||
|
|
||||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
|
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
osig->data_type(IVL_VT_LOGIC);
|
osig->data_type(expr_type());
|
||||||
osig->set_signed(has_sign());
|
osig->set_signed(has_sign());
|
||||||
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
|
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
|
||||||
connect(osig->pin(0), con->pin(0));
|
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 (csig == 0 || tsig == 0 || fsig == 0) return 0;
|
||||||
|
|
||||||
if (tsig->data_type() != fsig->data_type()) {
|
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
|
||||||
cerr << get_fileline() << ": error: True and False clauses of "
|
cerr << get_fileline() << ": internal error: "
|
||||||
"ternary expression have different types." << endl;
|
<< " True and False clauses of ternary expression "
|
||||||
|
<< " have incompatible types." << endl;
|
||||||
cerr << get_fileline() << ": : True clause is: "
|
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: "
|
cerr << get_fileline() << ": : False clause is: "
|
||||||
<< fsig->data_type() << endl;
|
<< fsig->data_type()
|
||||||
|
<< " (" << false_val_->expr_type() << "): "
|
||||||
|
<< *false_val_ << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
||||||
|
|
|
||||||
|
|
@ -502,7 +502,8 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||||
* ivl_const_bits
|
* ivl_const_bits
|
||||||
* This returns a pointer to an array of constant characters,
|
* This returns a pointer to an array of constant characters,
|
||||||
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
|
* 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
|
* ivl_const_nex
|
||||||
* Return the ivl_nexus_t of the output for the constant.
|
* Return the ivl_nexus_t of the output for the constant.
|
||||||
|
|
|
||||||
|
|
@ -3565,6 +3565,9 @@ class NetETernary : public NetExpr {
|
||||||
virtual void dump(ostream&) const;
|
virtual void dump(ostream&) const;
|
||||||
virtual NetNet*synthesize(Design*, NetScope*scope);
|
virtual NetNet*synthesize(Design*, NetScope*scope);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetExpr*cond_;
|
NetExpr*cond_;
|
||||||
NetExpr*true_val_;
|
NetExpr*true_val_;
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
|
||||||
assert(net);
|
assert(net);
|
||||||
switch (net->type) {
|
switch (net->type) {
|
||||||
|
|
||||||
|
case IVL_VT_BOOL:
|
||||||
case IVL_VT_LOGIC:
|
case IVL_VT_LOGIC:
|
||||||
if (net->width_ <= sizeof(net->b.bit_))
|
if (net->width_ <= sizeof(net->b.bit_))
|
||||||
return net->b.bit_;
|
return net->b.bit_;
|
||||||
|
|
|
||||||
6
t-dll.cc
6
t-dll.cc
|
|
@ -2199,7 +2199,7 @@ bool dll_target::net_const(const NetConst*net)
|
||||||
|
|
||||||
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
|
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. */
|
/* constants have a single vector output. */
|
||||||
assert(net->pin_count() == 1);
|
assert(net->pin_count() == 1);
|
||||||
|
|
@ -2223,9 +2223,13 @@ bool dll_target::net_const(const NetConst*net)
|
||||||
bits[idx] = '1';
|
bits[idx] = '1';
|
||||||
break;
|
break;
|
||||||
case verinum::Vx:
|
case verinum::Vx:
|
||||||
|
if (obj->type == IVL_VT_BOOL)
|
||||||
|
obj->type = IVL_VT_LOGIC;
|
||||||
bits[idx] = 'x';
|
bits[idx] = 'x';
|
||||||
break;
|
break;
|
||||||
case verinum::Vz:
|
case verinum::Vz:
|
||||||
|
if (obj->type == IVL_VT_BOOL)
|
||||||
|
obj->type = IVL_VT_LOGIC;
|
||||||
bits[idx] = 'z';
|
bits[idx] = 'z';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1058,8 +1058,10 @@ static void signal_nexus_const(ivl_signal_t sig,
|
||||||
fprintf(out, " const-");
|
fprintf(out, " const-");
|
||||||
|
|
||||||
switch (ivl_const_type(con)) {
|
switch (ivl_const_type(con)) {
|
||||||
|
case IVL_VT_BOOL:
|
||||||
case IVL_VT_LOGIC:
|
case IVL_VT_LOGIC:
|
||||||
bits = ivl_const_bits(con);
|
bits = ivl_const_bits(con);
|
||||||
|
assert(bits);
|
||||||
for (idx = 0 ; idx < width ; idx += 1) {
|
for (idx = 0 ; idx < width ; idx += 1) {
|
||||||
fprintf(out, "%c", bits[width-idx-1]);
|
fprintf(out, "%c", bits[width-idx-1]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue