Skip to content

Commit

Permalink
Added cast to type support (#4284)
Browse files Browse the repository at this point in the history
  • Loading branch information
rherveille authored Sep 29, 2024
1 parent 8e1e2b9 commit ce7db66
Show file tree
Hide file tree
Showing 4 changed files with 573 additions and 2 deletions.
16 changes: 15 additions & 1 deletion frontends/ast/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, ";\n");
break;

case AST_WIRETYPE:
fprintf(f, "%s", id2vl(str).c_str());
break;

case AST_MEMORY:
fprintf(f, "%s" "memory", indent.c_str());
if (is_signed)
Expand Down Expand Up @@ -694,7 +698,17 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break;

case AST_CAST_SIZE:
children[0]->dumpVlog(f, "");
switch (children[0]->type)
{
case AST_WIRE:
if (children[0]->children.size() > 0)
children[0]->children[0]->dumpVlog(f, "");
else
fprintf(f, "%d'", children[0]->range_left - children[0]->range_right + 1);
break;
default:
children[0]->dumpVlog(f, "");
}
fprintf(f, "'(");
children[1]->dumpVlog(f, "");
fprintf(f, ")");
Expand Down
60 changes: 59 additions & 1 deletion frontends/ast/simplify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1500,11 +1500,69 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
break;

case AST_CAST_SIZE: {
int width = 1;
AstNode *node;
AstNode *child = children[0];

if (child->type == AST_WIRE) {
if (child->children.size() == 0) {
// Base type (e.g., int)
width = child->range_left - child->range_right +1;
node = mkconst_int(width, child->is_signed);
} else {
// User defined type
log_assert(child->children[0]->type == AST_WIRETYPE);

const std::string &type_name = child->children[0]->str;
if (!current_scope.count(type_name))
input_error("Unknown identifier `%s' used as type name\n", type_name.c_str());
AstNode *resolved_type_node = current_scope.at(type_name);
if (resolved_type_node->type != AST_TYPEDEF)
input_error("`%s' does not name a type\n", type_name.c_str());
log_assert(resolved_type_node->children.size() == 1);
AstNode *template_node = resolved_type_node->children[0];

// Ensure typedef itself is fully simplified
while (template_node->simplify(const_fold, stage, width_hint, sign_hint)) {};

switch (template_node->type)
{
case AST_WIRE: {
if (template_node->children.size() > 0 && template_node->children[0]->type == AST_RANGE)
width = range_width(this, template_node->children[0]);
child->delete_children();
node = mkconst_int(width, true);
break;
}

case AST_STRUCT:
case AST_UNION: {
child->delete_children();
width = size_packed_struct(template_node, 0);
node = mkconst_int(width, false);
break;
}

default:
log_error("Don't know how to translate static cast of type %s\n", type2str(template_node->type).c_str());
}
}

delete child;
children.erase(children.begin());
children.insert(children.begin(), node);
}

detect_width_simple = true;
children_are_self_determined = true;
break;
}

case AST_TO_BITS:
case AST_TO_SIGNED:
case AST_TO_UNSIGNED:
case AST_SELFSZ:
case AST_CAST_SIZE:
case AST_CONCAT:
case AST_REPLICATE:
case AST_REDUCE_AND:
Expand Down
6 changes: 6 additions & 0 deletions frontends/verilog/verilog_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -3506,6 +3506,12 @@ basic_expr:
$$ = new AstNode(AST_CAST_SIZE, $1, $4);
SET_AST_NODE_LOC($$, @1, @4);
} |
typedef_base_type OP_CAST '(' expr ')' {
if (!sv_mode)
frontend_verilog_yyerror("Static cast is only supported in SystemVerilog mode.");
$$ = new AstNode(AST_CAST_SIZE, $1, $4);
SET_AST_NODE_LOC($$, @1, @4);
} |
'(' expr '=' expr ')' {
ensureAsgnExprAllowed();
AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $4);
Expand Down
Loading

0 comments on commit ce7db66

Please sign in to comment.