Skip to content

Commit dc9605a

Browse files
committed
yosys-systemverilog: fix multirange with dot usage
Signed-off-by: Kamil Rakoczy <[email protected]>
1 parent 56f957c commit dc9605a

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

systemverilog-plugin/UhdmAst.cc

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)