@@ -962,29 +962,47 @@ 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- if (node->children [0 ]->type == AST::AST_RANGE) {
966- int struct_size_int = get_max_offset_struct (struct_node) + 1 ;
967- log_assert (!wire_node->multirange_dimensions .empty ());
968- int range = wire_node->multirange_dimensions .back () - 1 ;
969- if (!wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .empty () &&
970- wire_node->attributes [UhdmAst::unpacked_ranges ()]->children .back ()->range_left == range) {
971- expanded->children [1 ] = new AST::AstNode (
972- AST::AST_ADD, expanded->children [1 ],
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- expanded->children [0 ] = new AST::AstNode (
976- AST::AST_ADD, expanded->children [0 ],
977- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ),
978- new AST::AstNode (AST::AST_SUB, AST::AstNode::mkconst_int (range, true , 32 ), node->children [0 ]->children [0 ]->clone ())));
979- } else {
980- expanded->children [1 ] = new AST::AstNode (
981- AST::AST_ADD, expanded->children [1 ],
982- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), node->children [0 ]->children [0 ]->clone ()));
983- expanded->children [0 ] = new AST::AstNode (
984- AST::AST_ADD, expanded->children [0 ],
985- new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), node->children [0 ]->children [0 ]->clone ()));
965+ std::vector<AST::AstNode *> struct_ranges;
966+ for (auto c : node->children ) {
967+ if (c->type == AST::AST_RANGE) {
968+ struct_ranges.push_back (c);
986969 }
987970 }
971+ 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'
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+ // Get reverse iterator of wire dimensions
984+ auto dimensions_it = wire_node->multirange_dimensions .rbegin ();
985+ unsigned long range_id = 0 ;
986+ 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
989+ log_assert ((*it)->children .size () == 1 );
990+ bool is_unpacked_range = range_id < wire_node_unpacked_ranges_size;
991+ // if unpacked range, select from back;
992+ 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 ())
994+ : (*it)->children [0 ]->clone ();
995+ // calculate which struct we selected
996+ auto move_offset = new AST::AstNode (AST::AST_MUL, AST::AstNode::mkconst_int (struct_size_int, true , 32 ), elem);
997+ // move our expanded dot to currently selected struct
998+ expanded->children [0 ] = new AST::AstNode (AST::AST_ADD, move_offset->clone (), expanded->children [0 ]);
999+ 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 ;
1004+ range_id++;
1005+ }
9881006 return expanded;
9891007}
9901008
0 commit comments