aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
authorDag Lem <dag@nimrod.no>2023-02-05 11:01:37 +0100
committerDag Lem <dag@nimrod.no>2023-02-05 17:09:51 +0100
commit777c589e8576b3f8fbe6621efffb1224b1f372b7 (patch)
tree395401a8183c5da3772fe1986970456288a74199 /frontends
parent26db5a11d3ab3657adb77f3a7d0cabbd19529033 (diff)
downloadyosys-777c589e8576b3f8fbe6621efffb1224b1f372b7.tar.gz
yosys-777c589e8576b3f8fbe6621efffb1224b1f372b7.tar.bz2
yosys-777c589e8576b3f8fbe6621efffb1224b1f372b7.zip
Handle range offsets in packed arrays within packed structs
This brings the metadata for packed arrays in packed structs in line with the metadata for unpacked arrays, and correctly handles the case when both lsb and msb in an address range are non-zero.
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/simplify.cc53
1 files changed, 31 insertions, 22 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 2dbabca28..5f9f9f49c 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);