@@ -306,32 +306,122 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
306306 });
307307
308308 for (obj .object .get ("items" ).? .array .items ) | item | {
309+ var register_ids : std .ArrayList (Database .RegisterID ) = .empty ;
310+ defer register_ids .deinit (allocator );
309311 const register_name = item .object .get ("name" ).? .string ;
310312 const description : ? []const u8 = if (item .object .get ("description" )) | desc | desc .string else null ;
311- const byte_offset = item .object .get ("byte_offset" ).? .integer ;
313+ const byte_offset : u64 = @intCast ( item .object .get ("byte_offset" ).? .integer ) ;
312314 const item_bit_size = if (item .object .get ("bit_size" )) | v | v .integer else 32 ;
315+ const maybe_count : ? u64 , const maybe_stride : ? u64 = if (item .object .get ("array" )) | array | blk : {
316+ if (array .object .get ("len" )) | count | {
317+ if (count .integer == 1 ) break :blk .{ null , null };
318+ if (array .object .get ("stride" )) | stride | {
319+ if (stride .integer > 4 ) {
320+ break :blk .{ @intCast (count .integer ), @intCast (stride .integer ) };
321+ }
322+ }
323+ break :blk .{ @intCast (count .integer ), null };
324+ }
313325
314- const register_id = try db .create_register (group_id , .{
315- .name = register_name ,
316- .description = description ,
317- .offset_bytes = @intCast (byte_offset ),
318- .size_bits = @intCast (item_bit_size ),
319- .count = if (item .object .get ("array" )) | array | blk : {
320- if (array .object .get ("len" )) | count | {
321- // ensure stride is always 4 for now, assuming that
322- // it's in bytes
323- const stride = array .object .get ("stride" ).? .integer ;
324- if (stride != 4 ) {
325- std .log .warn ("ignoring register array with unsupported stride: {} != 4 for register {s} in {s} in {s}" , .{ stride , register_name , key ["block/" .len .. ], name });
326- break :blk null ;
326+ break :blk .{ null , null };
327+ } else .{ null , null };
328+
329+ // This register can be a cluster. In this case we can reference its type only.
330+ // We still need to handle the stride. This is the reason we need to compute size
331+ // of cluster.
332+ if (item .object .get ("block" )) | block | {
333+ const ref_type = block .string ;
334+ const block_key = try std .fmt .allocPrint (allocator , "block/{s}" , .{ref_type });
335+ const block_value = (register_file .value .object .get (block_key ) orelse continue ).object ;
336+ var max_bytes : u64 = 0 ;
337+ for (block_value .get ("items" ).? .array .items ) | nested_item | {
338+ // Let's assume we do not recurse on block
339+ const offset : u64 = @intCast (nested_item .object .get ("byte_offset" ).? .integer );
340+ if (nested_item .object .get ("array" )) | array | {
341+ if (array .object .get ("len" )) | count | {
342+ if (array .object .get ("stride" )) | stride | {
343+ max_bytes = @max (offset + 4 + @as (u64 , @intCast (stride .integer * (count .integer - 1 ))), max_bytes );
344+ continue ;
345+ }
327346 }
347+ }
348+ max_bytes = @max (offset + 4 , max_bytes );
349+ }
328350
329- break :blk @intCast (count .integer );
351+ if (maybe_stride == max_bytes ) {
352+ // We have a contiguous cluster array
353+ _ = try db .create_register (group_id , .{
354+ .name = register_name ,
355+ .description = description ,
356+ .ref_type = ref_type ,
357+ .offset_bytes = @intCast (byte_offset ),
358+ .size_bits = max_bytes * 8 ,
359+ .count = maybe_count ,
360+ });
361+ continue ;
362+ } else if (maybe_stride ) | stride | {
363+ // We have spread cluster
364+ for (0.. maybe_count .? ) | id | {
365+ const register_part_name = try std .fmt .allocPrint (allocator , "{s}[{d}]" , .{
366+ register_name ,
367+ id ,
368+ });
369+ _ = try db .create_register (group_id , .{
370+ .name = register_part_name ,
371+ .description = description ,
372+ .ref_type = ref_type ,
373+ .offset_bytes = byte_offset + (id * stride ),
374+ .size_bits = max_bytes * 8 ,
375+ .count = null ,
376+ });
330377 }
378+ continue ;
379+ } else if (maybe_stride == null ) {
380+ // We have a single cluster
381+ _ = try db .create_register (group_id , .{
382+ .name = register_name ,
383+ .description = description ,
384+ .ref_type = ref_type ,
385+ .offset_bytes = @intCast (byte_offset ),
386+ .size_bits = max_bytes * 8 ,
387+ .count = null ,
388+ });
389+ continue ;
390+ }
391+ // No match default to u32
392+ // At this point it should be unreachable.
393+ // I leave this comment as a placeholder for other special cases.
394+ }
331395
332- break :blk null ;
333- } else null ,
334- });
396+ // Not a cluster but a fieldset
397+ if (maybe_stride ) | stride | {
398+ if (maybe_count ) | count | {
399+ // We spread the register as it jumps over other registers
400+ for (0.. count ) | id | {
401+ const register_part_name = try std .fmt .allocPrint (allocator , "{s}[{d}]" , .{
402+ register_name ,
403+ id ,
404+ });
405+ const register_id = try db .create_register (group_id , .{
406+ .name = register_part_name ,
407+ .description = description ,
408+ .offset_bytes = byte_offset + (id * stride ),
409+ .size_bits = @intCast (item_bit_size ),
410+ .count = null ,
411+ });
412+ try register_ids .append (allocator , register_id );
413+ }
414+ }
415+ } else {
416+ const register_id = try db .create_register (group_id , .{
417+ .name = register_name ,
418+ .description = description ,
419+ .offset_bytes = @intCast (byte_offset ),
420+ .size_bits = @intCast (item_bit_size ),
421+ .count = maybe_count ,
422+ });
423+ try register_ids .append (allocator , register_id );
424+ }
335425
336426 if (item .object .get ("fieldset" )) | fieldset | blk : {
337427 const fieldset_key = try std .fmt .allocPrint (allocator , "fieldset/{s}" , .{fieldset .string });
@@ -356,7 +446,7 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
356446 // these are evenly spaced and much nicer to work with.
357447
358448 array_count = if (object_map .get ("len" )) | len | @intCast (len .integer ) else null ;
359- array_stride = if (object_map .get ("stride" )) | stride | @intCast (stride .integer ) else null ;
449+ array_stride = if (object_map .get ("stride" )) | field_stride | @intCast (field_stride .integer ) else null ;
360450
361451 // This category where there is an array of items, but it is given by
362452 // individual offsets as opposed to a count + stride. This is used when strides are
@@ -365,30 +455,32 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
365455 if (object_map .get ("offsets" )) | positions | {
366456 for (positions .array .items , 0.. ) | position , idx | {
367457 const field_name_irregular_stride = try std .fmt .allocPrint (allocator , "{s}[{}]" , .{ field_name , idx });
368-
369- try db .add_register_field (register_id , .{
370- .name = field_name_irregular_stride ,
371- .description = field_description ,
372- .offset_bits = @intCast (position .integer + bit_offset ),
373- .size_bits = @intCast (bit_size ),
374- .enum_id = enum_id ,
375- .count = null ,
376- .stride = null ,
377- });
458+ for (register_ids .items ) | register_id | {
459+ try db .add_register_field (register_id , .{
460+ .name = field_name_irregular_stride ,
461+ .description = field_description ,
462+ .offset_bits = @intCast (position .integer + bit_offset ),
463+ .size_bits = @intCast (bit_size ),
464+ .enum_id = enum_id ,
465+ .count = null ,
466+ .stride = null ,
467+ });
468+ }
378469 }
379470 continue :next_field ;
380471 }
381472 }
382-
383- try db .add_register_field (register_id , .{
384- .name = field_name ,
385- .description = field_description ,
386- .offset_bits = @intCast (bit_offset ),
387- .size_bits = @intCast (bit_size ),
388- .enum_id = enum_id ,
389- .count = array_count ,
390- .stride = array_stride ,
391- });
473+ for (register_ids .items ) | register_id | {
474+ try db .add_register_field (register_id , .{
475+ .name = field_name ,
476+ .description = field_description ,
477+ .offset_bits = @intCast (bit_offset ),
478+ .size_bits = @intCast (bit_size ),
479+ .enum_id = enum_id ,
480+ .count = array_count ,
481+ .stride = array_stride ,
482+ });
483+ }
392484 },
393485 .array = > | arr | {
394486 // This case is for discontinuous fields where the first few bits are
@@ -411,18 +503,19 @@ pub fn load_into_db(db: *Database, path: []const u8, device: ?[]const u8) !void
411503 var array_stride : ? u8 = null ;
412504 if (field .object .get ("array" )) | array | {
413505 array_count = if (array .object .get ("len" )) | len | @intCast (len .integer ) else null ;
414- array_stride = if (array .object .get ("stride" )) | stride | @intCast (stride .integer ) else null ;
506+ array_stride = if (array .object .get ("stride" )) | field_stride | @intCast (field_stride .integer ) else null ;
507+ }
508+ for (register_ids .items ) | register_id | {
509+ try db .add_register_field (register_id , .{
510+ .name = non_contiguous_field_name ,
511+ .description = field_description ,
512+ .offset_bits = @intCast (bit_offset ),
513+ .size_bits = @intCast (bit_size ),
514+ .enum_id = enum_id ,
515+ .count = array_count ,
516+ .stride = array_stride ,
517+ });
415518 }
416-
417- try db .add_register_field (register_id , .{
418- .name = non_contiguous_field_name ,
419- .description = field_description ,
420- .offset_bits = @intCast (bit_offset ),
421- .size_bits = @intCast (bit_size ),
422- .enum_id = enum_id ,
423- .count = array_count ,
424- .stride = array_stride ,
425- });
426519 }
427520 },
428521 else = > | val | {
@@ -603,4 +696,3 @@ const std = @import("std");
603696const Database = @import ("Database.zig" );
604697const Arch = @import ("arch.zig" ).Arch ;
605698const arm = @import ("arch/arm.zig" );
606- const FS_Directory = @import ("FS_Directory.zig" );
0 commit comments