@@ -962,15 +962,19 @@ static AST::AstNode *convert_dot(AST::AstNode *wire_node, AST::AstNode *node, AS
962962 }
963963 log_assert (struct_node);
964964 auto expanded = expand_dot (struct_node, dot);
965+ // Now expand ranges that are at instance part of dotted reference
966+ // `expand_dot` returns AST_RANGE with 2 children that selects member pointed by dotted reference
967+ // now we need to move this range to select correct struct
965968 std::vector<AST::AstNode *> struct_ranges;
966969 for (auto c : node->children ) {
967970 if (c->type == AST::AST_RANGE) {
968971 struct_ranges.push_back (c);
969972 }
970973 }
974+ log_assert (wire_node->attributes .count (UhdmAst::unpacked_ranges ()));
975+ log_assert (wire_node->attributes .count (UhdmAst::packed_ranges ()));
976+ log_assert (struct_ranges.size () <= (wire_node->multirange_dimensions .size () / 2 ));
971977 const auto wire_node_unpacked_ranges_size = wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .size ();
972- // 'dot' notation can only be used on specific struct element
973- // '1' packed range is from wiretype and it is already expanded in 'expand_dot'
974978 // TODO(krak): wire ranges are sometimes under wiretype node (e.g. in case of typedef)
975979 // but wiretype ranges contains also struct range that is already expanded in 'expand_dot'
976980 // we need to find a way to calculate size of wire ranges without struct range here to enable this assert
@@ -980,27 +984,25 @@ static AST::AstNode *convert_dot(AST::AstNode *wire_node, AST::AstNode *node, AS
980984
981985 // Get size of single structure
982986 int struct_size_int = get_max_offset_struct (struct_node) + 1 ;
983- // Get reverse iterator of wire dimensions
984- auto dimensions_it = wire_node->multirange_dimensions .rbegin ();
987+ auto wire_dimension_size_it = wire_node->multirange_dimensions .rbegin ();
985988 unsigned long range_id = 0 ;
986989 for (auto it = struct_ranges.rbegin (); it != struct_ranges.rend (); it++) {
987- // in 'dot' context, we need to select specific struct
988- // element, so assert that there is only 1 child (range with single const) in struct
990+ // in 'dot' context, we need to select specific struct element,
991+ // so assert that there is only 1 child in struct range (range with single child)
989992 log_assert ((*it)->children .size () == 1 );
990993 bool is_unpacked_range = range_id < wire_node_unpacked_ranges_size;
991- // if unpacked range, select from back;
994+ // if unpacked range, select from back
992995 auto elem = is_unpacked_range
993- ? new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (*dimensions_it - 1 , true , 32 ), (*it)->children [0 ]->clone ())
996+ ? new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (*wire_dimension_size_it - 1 , true , 32 ), (*it)->children [0 ]->clone ())
994997 : (*it)->children [0 ]->clone ();
995998 // calculate which struct we selected
996999 auto move_offset = new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), elem);
9971000 // move our expanded dot to currently selected struct
9981001 expanded->children [0 ] = new AST::AstNode (AST::AST_ADD, move_offset->clone (), expanded->children [0 ]);
9991002 expanded->children [1 ] = new AST::AstNode (AST::AST_ADD, move_offset, expanded->children [1 ]);
1000- // next range, multiply struct_size_int by whole dimension size
1001- struct_size_int *= *dimensions_it;
1002- // move iterator to next dimension width
1003- dimensions_it += 2 ;
1003+ struct_size_int *= *wire_dimension_size_it;
1004+ // wire_dimension_size stores interleaved offset and size. Move to next dimension's size
1005+ wire_dimension_size_it += 2 ;
10041006 range_id++;
10051007 }
10061008 return expanded;
0 commit comments