Skip to content

Commit

Permalink
Add error message if struct is not fully defined (#192).
Browse files Browse the repository at this point in the history
Fix omission of 6.3.2.3.2-b: Auto-assign default values to unset members of struct literals
  • Loading branch information
amykyta3 committed Nov 7, 2023
1 parent 43300c1 commit c14b8c8
Show file tree
Hide file tree
Showing 17 changed files with 1,078 additions and 940 deletions.
32 changes: 32 additions & 0 deletions systemrdl/core/ExprVisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,38 @@ def visitStruct_literal(self, ctx: SystemRDLParser.Struct_literalContext):

values[member_name] = (member_expr, member_name_src_ref)

missing_members = set(struct_type._members.keys()) - set(values.keys())
undefined_members = []
for member_name in missing_members:
# 6.3.2.3.2-b: When defining struct member values, unassigned members
# shall receive a default value depending on their type, when available:
t = struct_type._members[member_name]
if t == bool:
values[member_name] = (ast.BoolLiteral(self.compiler.env, None, False), None)
elif t == str:
values[member_name] = (ast.StringLiteral(self.compiler.env, None, ""), None)
elif t == rdltypes.AccessType:
v = ast.BuiltinEnumLiteral(self.compiler.env, None, rdltypes.AccessType.rw)
values[member_name] = (v, None)
elif t == rdltypes.AddressingType:
v = ast.BuiltinEnumLiteral(self.compiler.env, None, rdltypes.AddressingType.regalign)
values[member_name] = (v, None)
elif isinstance(t, rdltypes.ArrayedType):
v = ast.ArrayLiteral(self.compiler.env, None, [])
values[member_name] = (v, None)
else:
undefined_members.append(member_name)

if undefined_members:
# 6.3.2.3.2-c: All the members from a struct instance shall be assigned
# a value, either explicitly or by default.
# Undefined struct members shall raise an error
self.msg.fatal(
"Incomplete struct literal '%s'. The following members are undefined: %s"
% (struct_type_name, ", ".join(undefined_members)),
src_ref_from_antlr(ctx.ID())
)

expr = ast.StructLiteral(
self.compiler.env,
src_ref_from_antlr(ctx.ID()),
Expand Down
9 changes: 4 additions & 5 deletions systemrdl/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,11 +937,10 @@ def total_size(self) -> int:
"""
assert isinstance(self.inst, comp.AddressableComponent)
if self.is_array:
# Total size of arrays is technically supposed to be:
# self.inst.array_stride * (self.inst.n_elements-1) + self.size
# However this opens up a whole slew of ugly corner cases that the
# spec designers may not have anticipated.
# Using a simplified calculation for now until someone actually cares
# RDL spec does not explicitly clarify this, but total size for arrays
# should include any additional trailing padding implied by the stride.
# This makes it consistent with IP-XACT.
# See discussion here: https://forums.accellera.org/topic/7529-interpretation-of-total-array-size-implicit-address-allocation/
return self.array_stride * self.inst.n_elements

else:
Expand Down
4 changes: 3 additions & 1 deletion systemrdl/parser/SystemRDL.g4

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/SystemRDL.interp

Large diffs are not rendered by default.

966 changes: 494 additions & 472 deletions systemrdl/parser/SystemRDLParser.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/SystemRDL.interp

Large diffs are not rendered by default.

933 changes: 479 additions & 454 deletions systemrdl/parser/ext/SystemRDLParser.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/sa_systemrdl_cpp_parser.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/sa_systemrdl_translator.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/sa_systemrdl_translator.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/speedy_antlr.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/ext/speedy_antlr.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion systemrdl/parser/sa_systemrdl.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions test/rdl_err_src/err_incomplete_struct.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
struct struct_t {
boolean a;
longint b;
};

property struct_prop {
type = struct_t;
component = field;
};

addrmap top {
reg {
field {
struct_prop = struct_t'{a: true};
} f;
} reg_error;
};
21 changes: 21 additions & 0 deletions test/rdl_src/incomplete_struct.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
struct struct_t {
boolean x;
boolean a;
string b;
accesstype c;
addressingtype d;
longint e[];
};

property struct_prop {
type = struct_t;
component = field;
};

addrmap top {
reg {
field {
struct_prop = struct_t'{};
} f1;
} r1;
};
7 changes: 7 additions & 0 deletions test/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ def test_bad_mem_child(self):
r"Definitions of 'addrmap' components not allowed inside a mem definition"
)

def test_incomplete_struct(self):
self.assertRDLCompileError(
["rdl_err_src/err_incomplete_struct.rdl"],
None,
r"Incomplete struct literal 'struct_t'. The following members are undefined: b"
)


class TestUserErrors(RDLSourceTestCase):
def setUp(self):
Expand Down
13 changes: 13 additions & 0 deletions test/test_structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,16 @@ def test_struct_pickleable(self):
self.assertEqual(struct._is_abstract, struct2._is_abstract)
self.assertIs(type(struct).__class__, type(struct2).__class__)
self.assertIs(type(struct).__module__, type(struct2).__module__)

def test_incomplete_struct(self):
root = self.compile(
["rdl_src/incomplete_struct.rdl"],
"top"
)

struct = root.find_by_path("top.r1.f1").get_property('struct_prop')
self.assertEqual(struct.a, False)
self.assertEqual(struct.b, "")
self.assertEqual(struct.c, rdlt.AccessType.rw)
self.assertEqual(struct.d, rdlt.AddressingType.regalign)
self.assertEqual(struct.e, [])

0 comments on commit c14b8c8

Please sign in to comment.