@@ -273,12 +273,13 @@ fn infer_enum_size(allocator: Allocator, module_node: xml.Node, value_group_node
273273 var field_sizes = std .ArrayList (u64 ).init (allocator );
274274 defer field_sizes .deinit ();
275275
276- var register_it = module_node .iterate (&.{}, &.{"register" });
276+ var register_it = module_node .iterate (&.{"register-group" }, &.{"register" });
277277 while (register_it .next ()) | register_node | {
278278 var bitfield_it = register_node .iterate (&.{}, &.{"bitfield" });
279279 while (bitfield_it .next ()) | bitfield_node | {
280280 if (bitfield_node .get_attribute ("values" )) | values | {
281281 if (std .mem .eql (u8 , values , value_group_name )) {
282+ log .debug ("found values={s}" , .{values });
282283 const mask_str = bitfield_node .get_attribute ("mask" ) orelse continue ;
283284 const mask = try std .fmt .parseInt (u64 , mask_str , 0 );
284285 try field_sizes .append (@popCount (mask ));
@@ -288,6 +289,8 @@ fn infer_enum_size(allocator: Allocator, module_node: xml.Node, value_group_node
288289 }
289290 }
290291
292+ log .debug ("found field usage count of: {}" , .{field_sizes .items .len });
293+
291294 // if all the field sizes are the same, and the max value can fit in there,
292295 // then set the size of the enum. If there are no usages of an enum, then
293296 // assign it the smallest value possible
@@ -305,8 +308,10 @@ fn infer_enum_size(allocator: Allocator, module_node: xml.Node, value_group_node
305308 return error .InconsistentEnumSizes ;
306309 }
307310
308- if (max_value > 0 and (std .math .log2_int (u64 , max_value ) + 1 ) > ret .? )
309- return error .EnumMaxValueTooBig ;
311+ if (max_value > 0 and (std .math .log2_int (u64 , max_value ) + 1 ) > ret .? ) {
312+ log .warn ("Uses of this enum are smaller than the calculated size" , .{});
313+ return std .math .log2_int (u64 , max_value );
314+ }
310315
311316 break :blk @intCast (ret .? );
312317 };
@@ -369,7 +374,7 @@ fn load_module_type(ctx: *Context, node: xml.Node) !void {
369374 // registers. This operation needs to be done in
370375 // `loadModuleInstance()` as well
371376 if (get_inlined_register_group (node , name )) | register_group_node | {
372- try load_register_group_children (ctx , register_group_node , struct_id );
377+ try load_register_group_children (ctx , register_group_node , peripheral , struct_id );
373378 } else {
374379 var register_group_it = node .iterate (&.{}, &.{"register-group" });
375380 while (register_group_it .next ()) | register_group_node |
@@ -407,6 +412,7 @@ fn load_module_interrupt_group_entry(
407412fn load_register_group_children (
408413 ctx : * Context ,
409414 node : xml.Node ,
415+ peripheral : PeripheralID ,
410416 parent : StructID ,
411417) ! void {
412418 var mode_it = node .iterate (&.{}, &.{"mode" });
@@ -416,9 +422,59 @@ fn load_register_group_children(
416422 return err ;
417423 };
418424
419- var register_it = node .iterate (&.{}, &.{ "register" , "register-group" });
425+ var register_it = node .iterate (&.{}, &.{"register" });
420426 while (register_it .next ()) | register_node |
421427 try load_register (ctx , register_node , parent );
428+
429+ var register_group_it = node .iterate (&.{}, &.{"register-group" });
430+ while (register_group_it .next ()) | register_group_node |
431+ try load_nested_register_group (ctx , register_group_node , peripheral , parent );
432+ }
433+
434+ fn load_nested_register_group (
435+ ctx : * Context ,
436+ node : xml.Node ,
437+ peripheral : PeripheralID ,
438+ parent : StructID ,
439+ ) ! void {
440+ const db = ctx .db ;
441+ log .debug ("load_nested_register_group: peripheral={} parent={}" , .{ peripheral , parent });
442+
443+ validate_attrs (node , &.{
444+ "name" ,
445+ "name-in-module" ,
446+ "offset" ,
447+ "size" ,
448+ "count" ,
449+ "caption" ,
450+ });
451+
452+ const name = node .get_attribute ("name" ) orelse return error .MissingRegisterName ;
453+ const name_in_module = node .get_attribute ("name-in-module" ) orelse return error .MissingNameInModule ;
454+
455+ const peripheral_struct_id = try db .get_peripheral_struct (peripheral );
456+ log .debug (" peripheral_struct_id={}" , .{peripheral_struct_id });
457+ const struct_id = try db .get_struct_decl_id_by_name (peripheral_struct_id , name_in_module );
458+ log .debug (" struct_id={}" , .{struct_id });
459+
460+ try db .add_nested_struct_field (parent , .{
461+ .name = name ,
462+ .struct_id = struct_id ,
463+ .offset_bytes = if (node .get_attribute ("offset" )) | offset_str |
464+ try std .fmt .parseInt (u64 , offset_str , 0 )
465+ else
466+ return error .MissingRegisterOffset ,
467+ .description = node .get_attribute ("caption" ),
468+
469+ .size_bytes = if (node .get_attribute ("size" )) | size_str |
470+ try std .fmt .parseInt (u64 , size_str , 0 )
471+ else
472+ null ,
473+ .count = if (node .get_attribute ("count" )) | count_str |
474+ try std .fmt .parseInt (u64 , count_str , 0 )
475+ else
476+ null ,
477+ });
422478}
423479
424480fn infer_register_group_offset (ctx : * Context , node : xml.Node , struct_id : StructID ) ! void {
@@ -439,34 +495,16 @@ fn infer_register_group_offset(ctx: *Context, node: xml.Node, struct_id: StructI
439495
440496// loads a register group which is under a peripheral or under another
441497// register-group
442- //
443- // TODO: implement nested register groups
444498fn load_register_group (ctx : * Context , node : xml.Node , parent : PeripheralID ) ! void {
445499 const db = ctx .db ;
446500
447- //switch (parent) {
448- // .peripheral =>
449-
450501 validate_attrs (node , &.{
451502 "name" ,
452503 "caption" ,
453504 "aligned" ,
454505 "section" ,
455506 "size" ,
456507 });
457- // .register_group => validate_attrs(node, &.{
458- // "name",
459- // "modes",
460- // "size",
461- // "name-in-module",
462- // "caption",
463- // "count",
464- // "start-index",
465- // "offset",
466- // }),
467- //}
468-
469- // TODO: for now just making register groups into structs.
470508
471509 const parent_struct_id = try db .get_peripheral_struct (parent );
472510 const struct_id = try db .create_nested_struct (parent_struct_id , .{
@@ -479,7 +517,7 @@ fn load_register_group(ctx: *Context, node: xml.Node, parent: PeripheralID) !voi
479517 });
480518
481519 try infer_register_group_offset (ctx , node , struct_id );
482- try load_register_group_children (ctx , node , struct_id );
520+ try load_register_group_children (ctx , node , parent , struct_id );
483521 // TODO: infer register group size?
484522 // Do register groups ever operate as just namespaces?
485523
@@ -786,6 +824,8 @@ fn load_enum(
786824 .size_bits = size_bits ,
787825 });
788826
827+ log .debug ("{}: name={s} inferred_size={}" , .{ enum_id , name , size_bits });
828+
789829 var value_it = node .iterate (&.{}, &.{"value" });
790830 while (value_it .next ()) | value_node |
791831 load_enum_field (ctx , value_node , enum_id ) catch {};
@@ -862,6 +902,7 @@ fn load_module_instance(
862902
863903 const struct_id = try ctx .db .get_peripheral_struct (peripheral_id );
864904
905+ //
865906 // register-group never has an offset in a module, so we can safely assume
866907 // that they're used as variants of a peripheral, and never used like
867908 // clusters in SVD.
0 commit comments