}
}
+ // resolve multiranges on memory decl
+ if (type == AST_MEMORY && children.size() > 1 && children[1]->type == AST_MULTIRANGE)
+ {
+ int total_size = 1;
+ multirange_dimensions.clear();
+ for (auto range : children[1]->children) {
+ if (!range->range_valid)
+ log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
+ multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
+ multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
+ total_size *= multirange_dimensions.back();
+ }
+ delete children[1];
+ children[1] = new AstNode(AST_RANGE, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size-1, true));
+ did_something = true;
+ }
+
+ // resolve multiranges on memory access
+ if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY && children.size() > 0 && children[0]->type == AST_MULTIRANGE)
+ {
+ AstNode *index_expr = nullptr;
+
+ for (int i = 0; 2*i < SIZE(id2ast->multirange_dimensions); i++)
+ {
+ if (SIZE(children[0]->children) < i)
+ log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
+
+ AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
+
+ if (id2ast->multirange_dimensions[2*i])
+ new_index_expr = new AstNode(AST_SUB, new_index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i], true));
+
+ if (i == 0)
+ index_expr = new_index_expr;
+ else
+ index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr);
+ }
+
+ for (int i = SIZE(id2ast->multirange_dimensions)/1; i < SIZE(children[0]->children); i++)
+ children.push_back(children[0]->children[i]->clone());
+
+ delete children[0];
+ if (index_expr == nullptr)
+ children.erase(children.begin());
+ else
+ children[0] = new AstNode(AST_RANGE, index_expr);
+
+ did_something = true;
+ }
+
// trim/extend parameters
if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
- (children[0]->children.size() == 1 || children[0]->children.size() == 2))
+ (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
{
std::stringstream sstr;
sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY
-%type <ast> wire_type range non_opt_range range_or_signed_int expr basic_expr concat_list rvalue lvalue lvalue_concat_list
+%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
+%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
%type <string> opt_label tok_prim_wrapper hierarchical_id
%type <boolean> opt_signed
%type <al> attr
$$->children.push_back($2);
};
+non_opt_multirange:
+ non_opt_range non_opt_range {
+ $$ = new AstNode(AST_MULTIRANGE, $1, $2);
+ } |
+ non_opt_multirange non_opt_range {
+ $$ = $1;
+ $$->children.push_back($2);
+ };
+
range:
non_opt_range {
$$ = $1;
$$ = NULL;
};
+range_or_multirange:
+ range { $$ = $1; } |
+ non_opt_multirange { $$ = $1; };
+
range_or_signed_int:
range {
$$ = $1;
};
wire_name:
- TOK_ID range {
+ TOK_ID range_or_multirange {
AstNode *node = astbuf1->clone();
node->str = *$1;
append_attr_clone(node, albuf);
$$->str = *$1;
delete $1;
} |
- hierarchical_id non_opt_range non_opt_range {
- $$ = new AstNode(AST_IDENTIFIER, $2, $3);
+ hierarchical_id non_opt_multirange {
+ $$ = new AstNode(AST_IDENTIFIER, $2);
$$->str = *$1;
delete $1;
};