diff options
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/simplify.cc | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 2dbabca28..f77b59d83 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -278,17 +278,21 @@ static int range_width(AstNode *node, AstNode *rnode) log_file_error(node->filename, node->location.first_line, "Unpacked array in packed struct/union member %s\n", node->str.c_str()); } -static void save_struct_array_width(AstNode *node, int width) +static void save_struct_range_dimensions(AstNode *node, AstNode *rnode) { - // stash the stride for the array - node->multirange_dimensions.push_back(width); - + node->multirange_dimensions.push_back(rnode->range_right); + node->multirange_dimensions.push_back(range_width(node, rnode)); + node->multirange_swapped.push_back(rnode->range_swapped); } -static void save_struct_range_swapped(AstNode *node, bool range_swapped) +static int get_struct_range_offset(AstNode *node, int dimension) { - node->multirange_swapped.push_back(range_swapped); + return node->multirange_dimensions[2*dimension]; +} +static int get_struct_range_width(AstNode *node, int dimension) +{ + return node->multirange_dimensions[2*dimension + 1]; } static int size_packed_struct(AstNode *snode, int base_offset) @@ -322,14 +326,17 @@ static int size_packed_struct(AstNode *snode, int base_offset) if (node->children[1]->type == AST_RANGE) { // Unpacked array, e.g. bit [63:0] a [0:3] auto rnode = node->children[1]; - // C-style array size, e.g. bit [63:0] a [4] - bool c_type = rnode->children.size() == 1; - int array_count = c_type ? rnode->range_left : range_width(node, rnode); - save_struct_array_width(node, array_count); - save_struct_range_swapped(node, rnode->range_swapped || c_type); - save_struct_array_width(node, width); - save_struct_range_swapped(node, node->children[0]->range_swapped); - width *= array_count; + if (rnode->children.size() == 1) { + // C-style array size, e.g. bit [63:0] a [4] + node->multirange_dimensions.push_back(0); + node->multirange_dimensions.push_back(rnode->range_left); + node->multirange_swapped.push_back(true); + width *= rnode->range_left; + } else { + save_struct_range_dimensions(node, rnode); + width *= range_width(node, rnode); + } + save_struct_range_dimensions(node, node->children[0]); } else { // The Yosys extension for unpacked arrays in packed structs / unions @@ -338,8 +345,7 @@ static int size_packed_struct(AstNode *snode, int base_offset) } } else { // Vector - save_struct_array_width(node, width); - save_struct_range_swapped(node, node->children[0]->range_swapped); + save_struct_range_dimensions(node, node->children[0]); } // range nodes are now redundant for (AstNode *child : node->children) @@ -355,10 +361,8 @@ static int size_packed_struct(AstNode *snode, int base_offset) } width = 1; for (auto rnode : node->children[0]->children) { - int rwidth = range_width(node, rnode); - save_struct_array_width(node, rwidth); - save_struct_range_swapped(node, rnode->range_swapped); - width *= rwidth; + save_struct_range_dimensions(node, rnode); + width *= range_width(node, rnode); } // range nodes are now redundant for (AstNode *child : node->children) @@ -422,9 +426,14 @@ static AstNode *normalize_struct_index(AstNode *expr, AstNode *member_node, int { expr = expr->clone(); + int offset = get_struct_range_offset(member_node, dimension); + if (offset) { + expr = new AstNode(AST_SUB, expr, node_int(offset)); + } + if (member_node->multirange_swapped[dimension]) { // The dimension has swapped range; swap index into the struct accordingly. - int msb = member_node->multirange_dimensions[dimension] - 1; + int msb = get_struct_range_width(member_node, dimension) - 1; expr = new AstNode(AST_SUB, node_int(msb), expr); } @@ -433,7 +442,7 @@ static AstNode *normalize_struct_index(AstNode *expr, AstNode *member_node, int static AstNode *struct_index_lsb_offset(AstNode *lsb_offset, AstNode *rnode, AstNode *member_node, int dimension, int &stride) { - stride /= member_node->multirange_dimensions[dimension]; + stride /= get_struct_range_width(member_node, dimension); auto right = normalize_struct_index(rnode->children.back(), member_node, dimension); auto offset = stride > 1 ? multiply_by_const(right, stride) : right; return new AstNode(AST_ADD, lsb_offset, offset); @@ -1016,7 +1025,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // create name resolution entries for all objects with names // also merge multiple declarations for the same wire (e.g. "output foobar; reg foobar;") - if (type == AST_MODULE) { + if (type == AST_MODULE || type == AST_INTERFACE) { current_scope.clear(); std::set<std::string> existing; int counter = 0; @@ -1701,7 +1710,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, current_filename = filename; - if (type == AST_MODULE) + if (type == AST_MODULE || type == AST_INTERFACE) current_scope.clear(); // convert defparam nodes to cell parameters @@ -4691,7 +4700,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg if (type == AST_MEMORY && (get_bool_attribute(ID::mem2reg) || (flags & AstNode::MEM2REG_FL_ALL) || !(is_reg || is_logic))) mem2reg_candidates[this] |= AstNode::MEM2REG_FL_FORCED; - if (type == AST_MODULE && get_bool_attribute(ID::mem2reg)) + if ((type == AST_MODULE || type == AST_INTERFACE) && get_bool_attribute(ID::mem2reg)) children_flags |= AstNode::MEM2REG_FL_ALL; dict<AstNode*, uint32_t> *proc_flags_p = NULL; |