Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/systemrdl/core/ExprVisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ 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())
# To ensure deterministic type names, the order of missing_members must be deterministic.
missing_members = sorted(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
Expand Down
6 changes: 5 additions & 1 deletion src/systemrdl/core/elaborate.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,11 @@ def exit_Component(self, node: Node) -> None:
for param_name, inst_parameter in node.inst.parameters_dict.items():
orig_param_value = node.inst.original_def.parameters_dict[param_name].get_value(node)
new_param_value = inst_parameter.get_value(node)
if new_param_value != orig_param_value:
if (new_param_value != orig_param_value) and not (
isinstance(new_param_value, rdltypes.UserStruct)
and isinstance(orig_param_value, rdltypes.UserStruct)
and new_param_value.members == orig_param_value.members
):
try:
segment = inst_parameter.get_normalized_parameter(node)
extra_type_name_segments.append(segment)
Expand Down
34 changes: 34 additions & 0 deletions test/rdl_src/parameterized_expr_nested_regfile.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
regfile top_inner_t #(longint FIELD_WIDTH = 2) {
reg {
field {} f[8+FIELD_WIDTH-1:8] = {FIELD_WIDTH{1'b1}};
} reg_x;

reg {
field {} g;
} reg_y;
reg_y->ispresent = (FIELD_WIDTH > 14);
};

regfile top_outer_t #(longint FIELD_WIDTH=14) {
top_inner_t #(.FIELD_WIDTH(FIELD_WIDTH)) rf_inner;
};

addrmap top {
regfile inner_t #(longint FIELD_WIDTH = 4) {
reg {
field {} f[8+FIELD_WIDTH-1:8] = {FIELD_WIDTH{1'b1}};
} reg_x;
};

regfile outer_t #(longint FIELD_WIDTH=10) {
inner_t #(.FIELD_WIDTH(FIELD_WIDTH)) rf_inner;
};

outer_t rf_default;
outer_t #(.FIELD_WIDTH(9)) rf_nine;
outer_t #(.FIELD_WIDTH(11)) rf_eleven;

top_outer_t top_rf_default;
top_outer_t #(.FIELD_WIDTH(13)) top_rf_thirteen;
top_outer_t #(.FIELD_WIDTH(15)) top_rf_fifteen;
};
10 changes: 10 additions & 0 deletions test/rdl_src/parameterized_expr_reg.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
addrmap top {

reg reg_t #(longint FIELD_WIDTH = 5) {
field {} f[8+FIELD_WIDTH-1:8] = {FIELD_WIDTH{1'b1}};
};

reg_t r_default;
reg_t #(.FIELD_WIDTH(4)) r_four;
reg_t #(.FIELD_WIDTH(6)) r_six;
};
16 changes: 16 additions & 0 deletions test/rdl_src/parameterized_expr_regfile.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
addrmap top {
regfile regfile_t #(longint FIELD_WIDTH = 5) {
reg {
field {} f[8+FIELD_WIDTH-1:8] = {FIELD_WIDTH{1'b1}};
} reg_x;

reg {
field {} g;
} reg_y;
reg_y->ispresent = (FIELD_WIDTH > 5);
};

regfile_t rf_default;
regfile_t #(.FIELD_WIDTH(4)) rf_four;
regfile_t #(.FIELD_WIDTH(6)) rf_six;
};
41 changes: 41 additions & 0 deletions test/rdl_src/parameterized_ispresent.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
addrmap top {

regfile regfile_t #(
bit REG_A_PRESENT = 1'b0,
bit REG_B_PRESENT = 1'b1,
longint X_F_RESET = 0
) {

reg {
field {} f[4];
} reg_x;

reg {
field {} f;
} reg_a;

reg {
field {} f;
} reg_b;

reg_x.f->reset = X_F_RESET + 1;
reg_a->ispresent = REG_A_PRESENT;
reg_b->ispresent = REG_B_PRESENT;
};

regfile_t f_b_present;

regfile_t #(
.REG_A_PRESENT(1'b1),
.REG_B_PRESENT(1'b0),
.X_F_RESET(2)
) f_a_present;

regfile_t #(
.REG_A_PRESENT(1'b1)
) f_both_present;

regfile_t #(
.REG_B_PRESENT(1'b0)
) f_none_present;
};
24 changes: 24 additions & 0 deletions test/rdl_src/parameterized_nested_types.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
addrmap top {

// A parameterized type definition which contains another regfile definition.
regfile a #(longint unsigned NUM_REGS = 1){
regfile b {
reg some_reg { field {} nested_field; } some_reg[NUM_REGS];
} b;
};

// An instantiation with default parameters (NUM_REGS=1).
a default_a;
// Another instantiation with a parameter override. The origin information for
// "b" will be uniquified with the parameter value.
a #(.NUM_REGS(2)) non_default_a;

// Another regfile which defines "b" in its scope. The origin should not
// collide with the version defined in "a" above.
regfile c {
regfile b {
reg some_reg { field {} nested_field; } some_reg;
} b;
} c;

};
28 changes: 28 additions & 0 deletions test/rdl_src/parameters.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,31 @@ addrmap myAmap {
external fixed_mem mem32;
external fixed_mem #(.word_size(64)) mem64;
};

//------------------------------------------------------------------------------

struct struct_t {
boolean x;
boolean a;
string b;
accesstype c;
addressingtype d;
longint e[];
};

reg struct_param_reg #(
struct_t STRUCT_1 = struct_t'{},
struct_t STRUCT_2 = struct_t'{},
struct_t STRUCT_3 = struct_t'{},
struct_t STRUCT_4 = struct_t'{}
){
field {} data;
};

addrmap struct_param {
struct_param_reg #(
.STRUCT_2(struct_t'{}),
.STRUCT_3(struct_t'{x: false}),
.STRUCT_4(struct_t'{a: true})
) spr;
};
121 changes: 120 additions & 1 deletion test/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ def checkme(r, X):
r3 = root.find_by_path("top.r3")
checkme(r3, 8)


def test_err_ref_in_parameter(self):
self.assertRDLCompileError(
["rdl_err_src/err_ref_in_parameter.rdl"],
Expand All @@ -306,3 +305,123 @@ def test_err_ref_in_parameter(self):
"parameters2",
r"Parameter 'PARAM' contains a reference. SystemRDL does not allow component references inside parameter values."
)

def test_struct_param(self):
root = self.compile(
["rdl_src/parameters.rdl"],
"struct_param"
)
spr = root.find_by_path("struct_param.spr")
self.assertEqual(spr.inst.type_name, "struct_param_reg_STRUCT_3_5d946c5b_STRUCT_4_55dee485")

def test_ispresent(self):
root = self.compile(['rdl_src/parameterized_ispresent.rdl'], 'top')

reg = root.find_by_path('top.f_b_present')
children = list(reg.children())
self.assertEqual(len(children), 2)
reg_x = children[0]
self.assertEqual(reg_x.inst_name, 'reg_x')
self.assertEqual(reg_x.get_child_by_name('f').get_property('reset'), 1)
self.assertEqual(children[1].inst_name, 'reg_b')

reg = root.find_by_path('top.f_a_present')
children = list(reg.children())
self.assertEqual(len(children), 2)
reg_x = children[0]
self.assertEqual(reg_x.inst_name, 'reg_x')
self.assertEqual(reg_x.get_child_by_name('f').get_property('reset'), 3)
self.assertEqual(children[1].inst_name, 'reg_a')

reg = root.find_by_path('top.f_both_present')
children = list(reg.children())
self.assertEqual(children[0].inst_name, 'reg_x')
self.assertEqual(children[1].inst_name, 'reg_a')
self.assertEqual(children[2].inst_name, 'reg_b')

reg = root.find_by_path('top.f_none_present')
children = list(reg.children())
self.assertEqual(len(children), 1)
self.assertEqual(children[0].inst_name, 'reg_x')

def test_nested_types(self):
root = self.compile(['rdl_src/parameterized_nested_types.rdl'], 'top')

regs = list(root.find_by_path('top.default_a.b.some_reg').unrolled())
self.assertEqual(len(regs), 1)
reg = regs[0]
fields = list(reg.fields())
self.assertEqual(len(fields), 1)
self.assertEqual(fields[0].inst_name, 'nested_field')

regs = list(root.find_by_path('top.non_default_a.b.some_reg').unrolled())
self.assertEqual(len(regs), 2)
reg = regs[0]
fields = list(reg.fields())
self.assertEqual(len(fields), 1)
self.assertEqual(fields[0].inst_name, 'nested_field')
reg = regs[1]
fields = list(reg.fields())
self.assertEqual(len(fields), 1)
self.assertEqual(fields[0].inst_name, 'nested_field')

regs = list(root.find_by_path('top.c.b.some_reg').unrolled())
self.assertEqual(len(regs), 1)
reg = regs[0]
fields = list(reg.fields())
self.assertEqual(len(fields), 1)
self.assertEqual(fields[0].inst_name, 'nested_field')

def test_expr_reg(self):
root = self.compile(['rdl_src/parameterized_expr_reg.rdl'], 'top')

field = root.find_by_path('top.r_default.f');
self.assertEqual(field.get_property('reset'), 0x1f);

field = root.find_by_path('top.r_four.f');
self.assertEqual(field.get_property('reset'), 0xf);

field = root.find_by_path('top.r_six.f');
self.assertEqual(field.get_property('reset'), 0x3f);

def test_expr_regfile(self):
root = self.compile(['rdl_src/parameterized_expr_regfile.rdl'], 'top')

field = root.find_by_path('top.rf_default.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x1f);

field = root.find_by_path('top.rf_four.reg_x.f');
self.assertEqual(field.get_property('reset'), 0xf);

field = root.find_by_path('top.rf_six.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x3f);

# y not present.
self.assertEqual(len(root.find_by_path('top.rf_default').registers()), 1)

# y not present.
self.assertEqual(len(root.find_by_path('top.rf_four').registers()), 1)

# y present.
self.assertEqual(len(root.find_by_path('top.rf_six').registers()), 2)

def test_expr_nested_regfile(self):
root = self.compile(['rdl_src/parameterized_expr_nested_regfile.rdl'], 'top')

field = root.find_by_path('top.rf_default.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x3ff); # 10 bits.

field = root.find_by_path('top.rf_nine.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x1ff); # 9 bits.

field = root.find_by_path('top.rf_eleven.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x7ff); # 11 bits.

field = root.find_by_path('top.top_rf_default.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x3fff); # 14 bits.

field = root.find_by_path('top.top_rf_thirteen.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x1fff); # 13 bits.

field = root.find_by_path('top.top_rf_fifteen.rf_inner.reg_x.f');
self.assertEqual(field.get_property('reset'), 0x7fff); # 15 bits.