diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 923aaa156..c8958c646 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -465,10 +465,17 @@ static AstNode *make_struct_index_range(AstNode *node, AstNode *rnode, int strid } } -static AstNode *slice_range(AstNode *rnode, AstNode *snode) +static AstNode *slice_range(AstNode *rnode, AstNode *snode, AstNode *member_node) { + if (member_node->multirange_swapped[1]) { + // The second dimension has swapped range; swap index into the struct accordingly. + int msb = member_node->multirange_dimensions[1] - 1; + for (auto &expr : snode->children) { + expr = new AstNode(AST_SUB, node_int(msb), expr); + } + } + // apply the bit slice indicated by snode to the range rnode - // TODO: Check for swapped indexes - see make_struct_index_range log_assert(rnode->type==AST_RANGE); auto left = rnode->children[0]; auto right = rnode->children[1]; @@ -504,7 +511,7 @@ AstNode *AST::make_struct_member_range(AstNode *node, AstNode *member_node) auto mrnode = node->children[0]; auto element_range = make_struct_index_range(node, mrnode->children[0], stride, range_right, member_node); // then apply bit slice range - auto range = slice_range(element_range, mrnode->children[1]); + auto range = slice_range(element_range, mrnode->children[1], member_node); delete element_range; return range; } diff --git a/tests/svtypes/struct_array.sv b/tests/svtypes/struct_array.sv index d33d18da2..e7d09b7c3 100644 --- a/tests/svtypes/struct_array.sv +++ b/tests/svtypes/struct_array.sv @@ -59,6 +59,27 @@ module top; always_comb assert(s3==80'hFC00_4200_0012_3400_FFFC); + // Same as s3, but with little endian bit addressing + struct packed { + bit [0:7] [0:7] a; // 8 element packed array of bytes + bit [0:15] b; // filler for non-zero offset + } s3_b; + + initial begin + s3_b = '0; + + s3_b.a[5:6] = 16'h1234; + s3_b.a[2] = 8'h42; + + s3_b.a[0] = '1; + s3_b.a[0][6:7] = '0; + + s3_b.b = '1; + s3_b.b[14:15] = '0; + end + + always_comb assert(s3_b==80'hFC00_4200_0012_3400_FFFC); + // Note that the tests below for unpacked arrays in structs rely on the // fact that they are actually packed in Yosys. @@ -104,6 +125,27 @@ module top; always_comb assert(s5==80'hFC00_4200_0012_3400_FFFC); + // Same as s5, but with little endian bit addressing + struct packed { + bit [0:7] a [0:7]; // 8 element unpacked array of bytes + bit [0:15] b; // filler for non-zero offset + } s5_b; + + initial begin + s5_b = '0; + + s5_b.a[5:6] = 16'h1234; + s5_b.a[2] = 8'h42; + + s5_b.a[0] = '1; + s5_b.a[0][6:7] = '0; + + s5_b.b = '1; + s5_b.b[14:15] = '0; + end + + always_comb assert(s5_b==80'hFC00_4200_0012_3400_FFFC); + // Same as s5, but using C-type unpacked array syntax struct packed { bit [7:0] a [8]; // 8 element unpacked array of bytes