diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index a8931a5..7a94631 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -62,10 +62,14 @@ fn RegisterProperties(comptime IndexType: type) type { /// register size in bits size: std.AutoHashMapUnmanaged(IndexType, usize) = .{}, access: std.AutoHashMapUnmanaged(IndexType, Access) = .{}, + reset_value: std.AutoHashMapUnmanaged(IndexType, u64) = .{}, + reset_mask: std.AutoHashMapUnmanaged(IndexType, u64) = .{}, fn deinit(register_properties: *@This(), allocator: Allocator) void { register_properties.size.deinit(allocator); register_properties.access.deinit(allocator); + register_properties.reset_value.deinit(allocator); + register_properties.reset_mask.deinit(allocator); } }; } @@ -166,6 +170,12 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { if (register_properties.access) |access| try db.register_properties.peripheral.access.put(db.gpa, peripheral_idx, access); + if (register_properties.reset_value) |reset_value| + try db.register_properties.peripheral.reset_value.put(db.gpa, peripheral_idx, reset_value); + + if (register_properties.reset_mask) |reset_mask| + try db.register_properties.peripheral.reset_mask.put(db.gpa, peripheral_idx, reset_mask); + var interrupt_it: ?*xml.Node = xml.findNode(peripheral_nodes, "interrupt"); while (interrupt_it != null) : (interrupt_it = xml.findNode(interrupt_it.?.next, "interrupt")) { const interrupt_nodes: *xml.Node = interrupt_it.?.children orelse continue; @@ -210,9 +220,14 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { if (cluster_register_props.size) |size| try db.register_properties.cluster.size.put(db.gpa, cluster_idx, size); - if (cluster_register_props.access) |access| { + if (cluster_register_props.access) |access| try db.register_properties.cluster.access.put(db.gpa, cluster_idx, access); - } + + if (cluster_register_props.reset_value) |reset_value| + try db.register_properties.cluster.reset_value.put(db.gpa, cluster_idx, reset_value); + + if (cluster_register_props.reset_mask) |reset_mask| + try db.register_properties.cluster.reset_mask.put(db.gpa, cluster_idx, reset_mask); try db.clusters_in_peripherals.append(db.gpa, .{ .cluster_idx = cluster_idx, @@ -336,6 +351,12 @@ fn loadRegisters( if (register_properties.access) |access| try db.register_properties.register.access.put(db.gpa, register_idx, access); + if (register_properties.reset_value) |reset_value| + try db.register_properties.register.reset_value.put(db.gpa, register_idx, reset_value); + + if (register_properties.reset_mask) |reset_mask| + try db.register_properties.register.reset_mask.put(db.gpa, register_idx, reset_mask); + const field_begin_idx = @intCast(FieldIndex, db.fields.items.len); if (xml.findNode(register_nodes, "fields")) |fields_node| { var field_it: ?*xml.Node = xml.findNode(fields_node.children, "field"); @@ -443,6 +464,12 @@ fn loadNestedClusters( if (register_properties.access) |access| try db.register_properties.cluster.access.put(db.gpa, cluster_idx, access); + if (register_properties.reset_value) |reset_value| + try db.register_properties.cluster.reset_value.put(db.gpa, cluster_idx, reset_value); + + if (register_properties.reset_mask) |reset_mask| + try db.register_properties.cluster.reset_mask.put(db.gpa, cluster_idx, reset_mask); + try db.clusters_in_clusters.append(db.gpa, .{ .parent_idx = parent_idx, .child_idx = cluster_idx, @@ -1451,12 +1478,30 @@ pub fn getRegister( peripheral_idx, ) orelse .read_write; + const reset_value: u64 = db.registerPropertyUpwardsSearch( + u64, + "reset_value", + reg_idx, + clusters.items, + peripheral_idx, + ) orelse 0; + + const reset_mask: u64 = db.registerPropertyUpwardsSearch( + u64, + "reset_mask", + reg_idx, + clusters.items, + peripheral_idx, + ) orelse std.math.maxInt(u64); + return Register{ .name = register.name, .description = register.description, .addr_offset = register.addr_offset, .size = size, .access = access, + .reset_value = reset_value, + .reset_mask = reset_mask, }; } diff --git a/tools/regz/src/Register.zig b/tools/regz/src/Register.zig index 1de935e..e419003 100644 --- a/tools/regz/src/Register.zig +++ b/tools/regz/src/Register.zig @@ -3,3 +3,5 @@ description: ?[]const u8, addr_offset: usize, size: ?usize, access: ?@import("svd.zig").Access, +reset_value: ?u64, +reset_mask: ?u64, diff --git a/tools/regz/src/atdf.zig b/tools/regz/src/atdf.zig index 53b8e37..23f0ee0 100644 --- a/tools/regz/src/atdf.zig +++ b/tools/regz/src/atdf.zig @@ -61,6 +61,10 @@ pub fn parseRegister(arena: *ArenaAllocator, node: *xml.Node, regs_start_addr: u } else return error.NoSize, // if this shows up then we need to determine the default size of a register // TODO: ATDF register access .access = .read_write, + // TODO: ATDF reset_value + .reset_value = null, + // TODO: ATDF reset_mask + .reset_mask = null, }; } diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 12c9243..19928ec 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -21,8 +21,8 @@ pub const Device = struct { size: ?usize = null, access: ?Access = null, protection: ?[]const u8 = null, - reset_value: ?[]const u8 = null, - reset_mask: ?[]const u8 = null, + reset_value: ?u64 = null, + reset_mask: ?u64 = null, }, pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !Device { @@ -48,8 +48,14 @@ pub const Device = struct { else null, .protection = if (xml.findValueForKey(nodes, "protection")) |str| try allocator.dupe(u8, str) else null, - .reset_value = if (xml.findValueForKey(nodes, "resetValue")) |str| try allocator.dupe(u8, str) else null, - .reset_mask = if (xml.findValueForKey(nodes, "resetMask")) |str| try allocator.dupe(u8, str) else null, + .reset_value = if (xml.findValueForKey(nodes, "resetValue")) |size_str| + try std.fmt.parseInt(u64, size_str, 0) + else + null, + .reset_mask = if (xml.findValueForKey(nodes, "resetMask")) |size_str| + try std.fmt.parseInt(u64, size_str, 0) + else + null, }, }; } @@ -241,6 +247,14 @@ pub fn parseRegister(arena: *ArenaAllocator, nodes: *xml.Node) !Register { .addr_offset = try std.fmt.parseInt(usize, xml.findValueForKey(nodes, "addressOffset") orelse return error.NoAddrOffset, 0), .size = null, .access = .read_write, + .reset_value = if (xml.findValueForKey(nodes, "resetValue")) |value| + try std.fmt.parseInt(u64, value, 0) + else + null, + .reset_mask = if (xml.findValueForKey(nodes, "resetMask")) |value| + try std.fmt.parseInt(u64, value, 0) + else + null, }; } @@ -401,11 +415,15 @@ pub const Dimension = struct { pub const RegisterProperties = struct { size: ?usize, access: ?Access, + reset_value: ?u64, + reset_mask: ?u64, pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !RegisterProperties { _ = arena; return RegisterProperties{ .size = try xml.parseIntForKey(usize, arena.child_allocator, nodes, "size"), + .reset_value = try xml.parseIntForKey(u64, arena.child_allocator, nodes, "resetValue"), + .reset_mask = try xml.parseIntForKey(u64, arena.child_allocator, nodes, "resetMask"), .access = if (xml.findValueForKey(nodes, "access")) |access_str| try Access.parse(access_str) else diff --git a/tools/regz/tests/svd.zig b/tools/regz/tests/svd.zig index 83809d6..9018f40 100644 --- a/tools/regz/tests/svd.zig +++ b/tools/regz/tests/svd.zig @@ -452,7 +452,406 @@ test "field.access" { try expectEqual(Access.read_only, db.field_access.get(0).?); } -//test "register.access" {} -// TODO: figure out if `protection` is interesting/important for us -//test "register.reset_value" {} -//test "register.reset_mask" {} +test "register.reset_value from device" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 1 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 1), register.reset_value.?); +} + +test "register.reset_value from peripheral" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 1 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ 2 + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 2), register.reset_value.?); +} + +test "register.reset_value from cluster" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 1 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ bruh + \\ 0x0 + \\ 2 + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 2), register.reset_value.?); +} + +test "register.reset_value from nested cluster" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 1 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ bruh + \\ 0x0 + \\ + \\ bruh2 + \\ 0x0 + \\ 2 + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 2), register.reset_value.?); +} + +test "register.reset_value from register" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 1 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ 42 + \\ 2 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 2), register.reset_value.?); +} + +// TODO: determine if assuming 0 by default is okay +test "register.reset_value missing" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0), register.reset_value.?); +} + +test "register.reset_mask from device" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 0xff + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0xff), register.reset_mask.?); +} + +test "register.reset_mask from peripheral" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 0xff + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ 0xffff + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0xffff), register.reset_mask.?); +} + +test "register.reset_mask from cluster" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 0xff + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ bruh + \\ 0x0 + \\ 0xffff + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0xffff), register.reset_mask.?); +} + +test "register.reset_mask from nested cluster" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 0xff + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ bruh + \\ 0x0 + \\ + \\ bruh2 + \\ 0x0 + \\ 0xffff + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0xffff), register.reset_mask.?); +} + +test "register.reset_mask from register" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ 32 + \\ 0xff + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ 42 + \\ 0xffff + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, 0xffff), register.reset_mask.?); +} + +// TODO: determine if assuming 0xffffffff by default is okay +test "register.reset_mask missing" { + var db = try initDbFromSvd( + \\ + \\ ARMCM3xxx + \\ 8 + \\ 32 + \\ + \\ + \\ TIMER0 + \\ 0x40010000 + \\ + \\ + \\ test + \\ 0x0 + \\ + \\ + \\ + \\ + \\ + \\ + ); + defer db.deinit(); + + const register_idx = 0; + const register = try db.getRegister(register_idx); + + try expectEqual(@as(u64, std.math.maxInt(u64)), register.reset_mask.?); +}