@@ -958,29 +958,49 @@ static AST::AstNode *convert_dot(AST::AstNode *wire_node, AST::AstNode *node, AS
958958 }
959959 log_assert (struct_node);
960960 auto expanded = expand_dot (struct_node, dot);
961- if (node->children [0 ]->type == AST::AST_RANGE) {
962- int struct_size_int = get_max_offset_struct (struct_node) + 1 ;
963- log_assert (!wire_node->multirange_dimensions .empty ());
964- int range = wire_node->multirange_dimensions .back () - 1 ;
965- if (!wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .empty () &&
966- wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .back ()->range_left == range) {
967- expanded->children [1 ] = new AST::AstNode (
968- AST::AST_ADD, expanded->children [1 ],
969- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ),
970- new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (range, true , 32 ), node->children [0 ]->children [0 ]->clone ())));
971- expanded->children [0 ] = new AST::AstNode (
972- AST::AST_ADD, expanded->children [0 ],
973- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ),
974- new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (range, true , 32 ), node->children [0 ]->children [0 ]->clone ())));
975- } else {
976- expanded->children [1 ] = new AST::AstNode (
977- AST::AST_ADD, expanded->children [1 ],
978- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), node->children [0 ]->children [0 ]->clone ()));
979- expanded->children [0 ] = new AST::AstNode (
980- AST::AST_ADD, expanded->children [0 ],
981- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), node->children [0 ]->children [0 ]->clone ()));
961+ // Now expand ranges that are at instance part of dotted reference
962+ // `expand_dot` returns AST_RANGE with 2 children that selects member pointed by dotted reference
963+ // now we need to move this range to select correct struct
964+ std::vector<AST::AstNode *> struct_ranges;
965+ for (auto c : node->children ) {
966+ if (c->type == AST::AST_RANGE) {
967+ struct_ranges.push_back (c);
982968 }
983969 }
970+ log_assert (wire_node->attributes .count (UhdmAst::unpacked_ranges ()));
971+ log_assert (wire_node->attributes .count (UhdmAst::packed_ranges ()));
972+ log_assert (struct_ranges.size () <= (wire_node->multirange_dimensions .size () / 2 ));
973+ const auto wire_node_unpacked_ranges_size = wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .size ();
974+ // TODO(krak): wire ranges are sometimes under wiretype node (e.g. in case of typedef)
975+ // but wiretype ranges contains also struct range that is already expanded in 'expand_dot'
976+ // we need to find a way to calculate size of wire ranges without struct range here to enable this assert
977+ // const auto wire_node_packed_ranges_size = wire_node->attributes[UhdmAst::packed_ranges()]->children.size();
978+ // const auto wire_node_ranges_size = wire_node_packed_ranges_size + wire_node_unpacked_ranges_size;
979+ // log_assert(struct_ranges.size() == (wire_node_ranges_size - 1));
980+
981+ // Get size of single structure
982+ int struct_size_int = get_max_offset_struct (struct_node) + 1 ;
983+ auto wire_dimension_size_it = wire_node->multirange_dimensions .rbegin ();
984+ unsigned long range_id = 0 ;
985+ for (auto it = struct_ranges.rbegin (); it != struct_ranges.rend (); it++) {
986+ // in 'dot' context, we need to select specific struct element,
987+ // so assert that there is only 1 child in struct range (range with single child)
988+ log_assert ((*it)->children .size () == 1 );
989+ bool is_unpacked_range = range_id < wire_node_unpacked_ranges_size;
990+ // if unpacked range, select from back
991+ auto elem = is_unpacked_range
992+ ? new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (*wire_dimension_size_it - 1 , true , 32 ), (*it)->children [0 ]->clone ())
993+ : (*it)->children [0 ]->clone ();
994+ // calculate which struct we selected
995+ auto move_offset = new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), elem);
996+ // move our expanded dot to currently selected struct
997+ expanded->children [0 ] = new AST::AstNode (AST::AST_ADD, move_offset->clone (), expanded->children [0 ]);
998+ expanded->children [1 ] = new AST::AstNode (AST::AST_ADD, move_offset, expanded->children [1 ]);
999+ struct_size_int *= *wire_dimension_size_it;
1000+ // wire_dimension_size stores interleaved offset and size. Move to next dimension's size
1001+ wire_dimension_size_it += 2 ;
1002+ range_id++;
1003+ }
9841004 return expanded;
9851005}
9861006
0 commit comments