Add support for explicit cast to enum

Assigning a value to an enum signal that is not of the same type as the
enum requires an explicit cast.

To support this attach the type of a type cast to the resulting expression.
This allows the assignment elaboration to confirm that value has been
explicitly cast to the right type.

Also handle the case where the value is a constant. In this case create a
NetEConstEnum instead of a NetEConst as the resulting expression.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-01-16 10:08:29 +01:00
parent 9b7c99b8a8
commit 053453c645
3 changed files with 15 additions and 8 deletions

View File

@ -3447,7 +3447,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
// the signedness pushed down from the main expression.
tmp = cast_to_width(sub, expr_width_, sub->has_sign(), *this);
}
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
return pad_to_width(tmp, expr_wid, signed_flag_, *this, target_type_);
}
if (dynamic_cast<const string_type_t*>(target_)) {

View File

@ -161,13 +161,13 @@ inline NetScope* symbol_search(const LineInfo*li,
* signed_flag.
*/
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info);
const LineInfo&info, ivl_type_t use_type = 0);
/*
* This version determines the extension method from the base expression type.
*/
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info, ivl_type_t use_type = 0)
{
return pad_to_width(expr, wid, expr->has_sign(), info);
return pad_to_width(expr, wid, expr->has_sign(), info, use_type);
}
/*

View File

@ -19,15 +19,16 @@
# include "config.h"
# include "netenum.h"
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
const LineInfo&info)
const LineInfo&info, ivl_type_t use_type)
{
if (wid <= expr->expr_width()) {
if (wid <= expr->expr_width() && !use_type) {
expr->cast_signed(signed_flag);
return expr;
}
@ -38,13 +39,19 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
verinum oval = tmp->value();
oval.has_sign(signed_flag);
oval = pad_to_width(oval, wid);
tmp = new NetEConst(oval);
if (const netenum_t *enum_type = dynamic_cast<const netenum_t *>(use_type)) {
// The name of the enum is set to <nil> here, but the name is
// only used in debugging output, so this is ok
tmp = new NetEConstEnum(perm_string(), enum_type, oval);
} else {
tmp = new NetEConst(oval);
}
tmp->set_line(info);
delete expr;
return tmp;
}
NetESelect*tmp = new NetESelect(expr, 0, wid);
NetESelect*tmp = new NetESelect(expr, 0, wid, use_type);
tmp->cast_signed(signed_flag);
tmp->set_line(info);
return tmp;