diff --git a/tools/regz/src/Database.zig b/tools/regz/src/Database.zig index adc3371..017a0ed 100644 --- a/tools/regz/src/Database.zig +++ b/tools/regz/src/Database.zig @@ -8,7 +8,6 @@ const Register = @import("Register.zig"); const Field = @import("Field.zig"); const Enumeration = @import("Enumeration.zig"); const cmsis = @import("cmsis.zig"); -pub const Access = svd.Access; const assert = std.debug.assert; const ArenaAllocator = std.heap.ArenaAllocator; @@ -16,6 +15,7 @@ const Allocator = std.mem.Allocator; const Database = @This(); +pub const Access = svd.Access; pub const PeripheralIndex = u32; pub const ClusterIndex = u32; pub const RegisterIndex = u32; @@ -61,7 +61,7 @@ const Nesting = enum { fn RegisterProperties(comptime IndexType: type) type { return struct { /// register size in bits - size: std.AutoHashMapUnmanaged(IndexType, usize) = .{}, + size: std.AutoHashMapUnmanaged(IndexType, u16) = .{}, access: std.AutoHashMapUnmanaged(IndexType, Access) = .{}, reset_value: std.AutoHashMapUnmanaged(IndexType, u64) = .{}, reset_mask: std.AutoHashMapUnmanaged(IndexType, u64) = .{}, @@ -108,6 +108,10 @@ dimensions: Dimensions = .{}, register_properties: RegisterPropertyTables = .{}, field_access: std.AutoArrayHashMapUnmanaged(FieldIndex, Access) = .{}, +/// Register addresses of registers we know will exist on an MCU, it's used for +/// deduplication when a vendor includes xml entries for those registers +system_reg_addrs: std.AutoArrayHashMapUnmanaged(u64, void) = .{}, + pub fn deinit(db: *Database) void { db.interrupts.deinit(db.gpa); db.peripherals.deinit(db.gpa); @@ -125,6 +129,7 @@ pub fn deinit(db: *Database) void { db.dimensions.deinit(db.gpa); db.register_properties.deinit(db.gpa); db.field_access.deinit(db.gpa); + db.system_reg_addrs.deinit(db.gpa); db.arena.deinit(); } @@ -147,6 +152,25 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { else null; + if (xml.findNode(device_nodes, "peripherals")) |peripherals_node| { + var peripheral_it: ?*xml.Node = xml.findNode(peripherals_node.children, "peripheral"); //peripherals_node.children; + while (peripheral_it != null) : (peripheral_it = xml.findNode(peripheral_it.?.next, "peripheral")) { + const peripheral_nodes: *xml.Node = peripheral_it.?.children orelse continue; + + 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; + const interrupt = try svd.Interrupt.parse(&db.arena, interrupt_nodes); + + // if the interrupt doesn't exist then do a sorted insert + if (std.sort.binarySearch(svd.Interrupt, interrupt, db.interrupts.items, {}, svd.Interrupt.compare) == null) { + try db.interrupts.append(db.gpa, interrupt); + std.sort.sort(svd.Interrupt, db.interrupts.items, {}, svd.Interrupt.lessThan); + } + } + } + } + if (db.cpu) |cpu| if (cpu.name) |cpu_name| if (svd.CpuName.parse(cpu_name)) |cpu_type| try cmsis.addCoreRegisters(&db, cpu_type); @@ -155,7 +179,7 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { defer named_derivations.deinit(allocator); if (xml.findNode(device_nodes, "peripherals")) |peripherals_node| { - var peripheral_it: ?*xml.Node = xml.findNode(peripherals_node.children, "peripheral"); //peripherals_node.children; + var peripheral_it: ?*xml.Node = xml.findNode(peripherals_node.children, "peripheral"); while (peripheral_it != null) : (peripheral_it = xml.findNode(peripheral_it.?.next, "peripheral")) { const peripheral_nodes: *xml.Node = peripheral_it.?.children orelse continue; const peripheral = try svd.parsePeripheral(&db.arena, peripheral_nodes); @@ -190,21 +214,18 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { .peripheral_idx = peripheral_idx, .interrupt_value = @intCast(u32, interrupt.value), }); - - // if the interrupt doesn't exist then do a sorted insert - if (std.sort.binarySearch(svd.Interrupt, interrupt, db.interrupts.items, {}, svd.Interrupt.compare) == null) { - try db.interrupts.append(db.gpa, interrupt); - std.sort.sort(svd.Interrupt, db.interrupts.items, {}, svd.Interrupt.lessThan); - } } if (xml.findNode(peripheral_nodes, "registers")) |registers_node| { const reg_begin_idx = db.registers.items.len; - try db.loadRegisters(registers_node.children, &named_derivations); - try db.registers_in_peripherals.put(db.gpa, peripheral_idx, .{ - .begin = @intCast(RegisterIndex, reg_begin_idx), - .end = @intCast(RegisterIndex, db.registers.items.len), - }); + { + const base_addr = if (peripheral.base_addr) |periph_base_addr| periph_base_addr else 0; + try db.loadRegisters(registers_node.children, base_addr, &named_derivations); + try db.registers_in_peripherals.put(db.gpa, peripheral_idx, .{ + .begin = @intCast(RegisterIndex, reg_begin_idx), + .end = @intCast(RegisterIndex, db.registers.items.len), + }); + } // process clusters, this might need to be recursive var cluster_it: ?*xml.Node = xml.findNode(registers_node.children, "cluster"); @@ -239,8 +260,13 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { .peripheral_idx = peripheral_idx, }); + const base_addr = if (peripheral.base_addr) |periph_base| + periph_base + cluster.addr_offset + else + cluster.addr_offset; + const first_reg_idx = db.registers.items.len; - try db.loadRegisters(cluster_nodes, &named_derivations); + try db.loadRegisters(cluster_nodes, base_addr, &named_derivations); try db.registers_in_clusters.put(db.gpa, cluster_idx, .{ .begin = @intCast(RegisterIndex, first_reg_idx), .end = @intCast(RegisterIndex, db.registers.items.len), @@ -334,12 +360,19 @@ pub fn initFromSvd(allocator: Allocator, doc: *xml.Doc) !Database { fn loadRegisters( db: *Database, nodes: ?*xml.Node, + base_addr: ?u64, named_derivations: *Derivations([]const u8), ) !void { var register_it: ?*xml.Node = xml.findNode(nodes, "register"); while (register_it != null) : (register_it = xml.findNode(register_it.?.next, "register")) { const register_nodes: *xml.Node = register_it.?.children orelse continue; const register = try svd.parseRegister(&db.arena, register_nodes); + if (base_addr) |ba| + if (db.system_reg_addrs.contains(ba + register.addr_offset)) { + std.log.debug("skipping register {s}, it is a system register", .{register.name}); + continue; + }; + const register_idx = @intCast(RegisterIndex, db.registers.items.len); try db.registers.append(db.gpa, register); @@ -481,7 +514,7 @@ fn loadNestedClusters( }); const first_reg_idx = db.registers.items.len; - try db.loadRegisters(cluster_nodes, named_derivations); + try db.loadRegisters(cluster_nodes, null, named_derivations); try db.registers_in_clusters.put(db.gpa, cluster_idx, .{ .begin = @intCast(RegisterIndex, first_reg_idx), .end = @intCast(RegisterIndex, db.registers.items.len), @@ -918,7 +951,7 @@ pub fn toZig(db: *Database, out_writer: anytype) !void { fn genZigCluster( db: *Database, writer: anytype, - base_addr: ?usize, + base_addr: ?u64, cluster_idx: ClusterIndex, nesting: Nesting, ) !void { @@ -987,9 +1020,9 @@ fn genZigSingleRegister( db: *Database, writer: anytype, name: []const u8, - width: usize, + width: u32, has_base_addr: bool, - addr_offset: usize, + addr_offset: u64, field_range_opt: ?IndexRange(FieldIndex), array_prefix: []const u8, nesting: Nesting, @@ -1258,8 +1291,8 @@ fn genZigFields( fn genZigRegister( db: *Database, writer: anytype, - base_addr: ?usize, - cluster_offset: ?usize, + base_addr: ?u64, + cluster_offset: ?u64, reg_idx: RegisterIndex, register: Register, nesting: Nesting, @@ -1524,8 +1557,8 @@ pub fn getRegister( db.findPeripheralContainingCluster(clusters.items[clusters.items.len - 1]) orelse return error.PeripheralNotFound; - const size = db.registerPropertyUpwardsSearch( - usize, + const size: u16 = db.registerPropertyUpwardsSearch( + u16, "size", reg_idx, clusters.items, @@ -1606,6 +1639,25 @@ pub fn addRegistersToCluster(db: *Database, cluster: ClusterIndex, registers: [] return range; } +pub fn addSystemRegisterAddresses( + db: *Database, + peripheral_idx: PeripheralIndex, + cluster_idx: ?ClusterIndex, + regs: IndexRange(RegisterIndex), +) !void { + const peripheral = db.peripherals.items[peripheral_idx]; + const base_address = if (peripheral.base_addr) |periph_base_addr| + if (cluster_idx) |ci| + periph_base_addr + db.clusters.items[ci].addr_offset + else + periph_base_addr + else + 0; + + for (db.registers.items[regs.begin..regs.end]) |register| + try db.system_reg_addrs.put(db.gpa, base_address + register.addr_offset, {}); +} + fn Derivations(comptime T: type) type { return struct { enumerations: std.AutoHashMapUnmanaged(EnumIndex, T) = .{}, diff --git a/tools/regz/src/Peripheral.zig b/tools/regz/src/Peripheral.zig index a21c67f..9ada52a 100644 --- a/tools/regz/src/Peripheral.zig +++ b/tools/regz/src/Peripheral.zig @@ -3,7 +3,7 @@ const std = @import("std"); name: []const u8, version: ?[]const u8, description: ?[]const u8, -base_addr: ?usize, +base_addr: ?u64, pub fn format( peripheral: @This(), diff --git a/tools/regz/src/Register.zig b/tools/regz/src/Register.zig index ede0d77..de7c574 100644 --- a/tools/regz/src/Register.zig +++ b/tools/regz/src/Register.zig @@ -2,8 +2,8 @@ const std = @import("std"); name: []const u8, description: ?[]const u8 = null, -addr_offset: usize, -size: ?usize = null, +addr_offset: u64, +size: ?u16 = null, access: ?@import("svd.zig").Access = null, reset_value: ?u64 = null, reset_mask: ?u64 = null, diff --git a/tools/regz/src/atdf.zig b/tools/regz/src/atdf.zig index 54ccac5..da82e64 100644 --- a/tools/regz/src/atdf.zig +++ b/tools/regz/src/atdf.zig @@ -45,7 +45,7 @@ pub fn parseRegister( reg_offset; } else return error.NoAddrOffset, .size = if (xml.getAttribute(node, "size")) |size_str| blk: { - const full_size = 8 * try std.fmt.parseInt(usize, size_str, 0); + const full_size = 8 * try std.fmt.parseInt(u16, size_str, 0); if (!has_fields) { const mask = try std.fmt.parseInt(u64, xml.getAttribute(node, "mask") orelse break :blk full_size, 0); diff --git a/tools/regz/src/cmsis.zig b/tools/regz/src/cmsis.zig index c7cc437..dea75ff 100644 --- a/tools/regz/src/cmsis.zig +++ b/tools/regz/src/cmsis.zig @@ -3,7 +3,9 @@ const svd = @import("svd.zig"); const Database = @import("Database.zig"); const cores = struct { + const cortex_m0 = @import("cmsis/cortex_m0.zig"); const cortex_m0plus = @import("cmsis/cortex_m0plus.zig"); + const cortex_m1 = @import("cmsis/cortex_m1.zig"); }; fn addSysTickRegisters(db: *Database, scs: Database.PeripheralIndex) !void { @@ -61,6 +63,8 @@ fn addSysTickRegisters(db: *Database, scs: Database.PeripheralIndex) !void { .{ .name = "SKEW", .offset = 30, .width = 1 }, .{ .name = "NOREF", .offset = 31, .width = 1 }, }); + + try db.addSystemRegisterAddresses(scs, systick, regs); } pub fn addCoreRegisters(db: *Database, cpu_name: svd.CpuName) !void { diff --git a/tools/regz/src/cmsis/cortex_m0.zig b/tools/regz/src/cmsis/cortex_m0.zig new file mode 100644 index 0000000..d7570f9 --- /dev/null +++ b/tools/regz/src/cmsis/cortex_m0.zig @@ -0,0 +1,232 @@ +const std = @import("std"); +const Database = @import("../Database.zig"); +const Register = @import("../Register.zig"); +const Field = @import("../Field.zig"); + +pub fn addCoreRegisters(db: *Database, scs: Database.PeripheralIndex) !void { + try addNvicCluster(db, scs); + try addScbCluster(db, scs); +} + +pub fn addNvicCluster(db: *Database, scs: Database.PeripheralIndex) !void { + const nvic = try db.addClusterToPeripheral(scs, .{ + .name = "NVIC", + .description = "Nested Vectored Interrupt Controller", + .addr_offset = 0x100, + }); + + const regs = try db.addRegistersToCluster(nvic, &.{ + .{ + .name = "ISER", + .description = "Interrupt Set Enable Register", + .addr_offset = 0x000, + }, + .{ + .name = "ICER", + .description = "Interrupt Clear Enable Register", + .addr_offset = 0x80, + }, + .{ + .name = "ISPR", + .description = "Interrupt Set Pending Register", + .addr_offset = 0x100, + }, + .{ + .name = "ICPR", + .description = "Interrupt Clear Pending Register", + .addr_offset = 0x180, + }, + }); + + var fields = std.ArrayList(Field).init(db.gpa); + defer fields.deinit(); + + for (db.interrupts.items) |interrupt| + try fields.append(.{ + .name = interrupt.name, + .offset = @intCast(u8, interrupt.value), + .width = 1, + }); + + const iser = regs.begin; + try db.addFieldsToRegister(iser, fields.items); + + const icer = regs.begin + 1; + try db.addFieldsToRegister(icer, fields.items); + + const ispr = regs.begin + 2; + try db.addFieldsToRegister(ispr, fields.items); + + const icpr = regs.begin + 3; + try db.addFieldsToRegister(icpr, fields.items); + + if (db.cpu) |cpu| if (cpu.nvic_prio_bits > 0) + try addInterruptPriorityRegisters(db, scs, nvic); + + try db.addSystemRegisterAddresses(scs, nvic, regs); +} + +fn addInterruptPriorityRegisters( + db: *Database, + scs: Database.PeripheralIndex, + nvic: Database.ClusterIndex, +) !void { + const ip_addr_offset = 0x300; + const nvic_prio_bits = db.cpu.?.nvic_prio_bits; + const peripheral = db.peripherals.items[scs]; + const cluster = db.clusters.items[nvic]; + const base_addr = if (peripheral.base_addr) |periph_base_addr| + periph_base_addr + cluster.addr_offset + else + cluster.addr_offset; + + var register_fields = std.ArrayList([]Field).init(db.gpa); + defer register_fields.deinit(); + + var registers = std.ArrayList(Register).init(db.gpa); + defer registers.deinit(); + + { + var i: u32 = 0; + while (i < 8) : (i += 1) { + // TODO: assert no duplicates in the interrupt table + var fields = std.ArrayListUnmanaged(Field){}; + errdefer fields.deinit(db.arena.allocator()); + + for (db.interrupts.items) |interrupt| { + if (i == interrupt.value / 4) { + try fields.append(db.arena.allocator(), .{ + .name = interrupt.name, + .offset = (8 * (@intCast(u8, interrupt.value) % 4)) + (8 - nvic_prio_bits), + .width = nvic_prio_bits, + }); + } + } + + const addr_offset = ip_addr_offset + (i * 4); + if (fields.items.len > 0) { + const reg_name = try std.fmt.allocPrint(db.arena.allocator(), "IP{}", .{ + i, + }); + + try registers.append(.{ + .name = reg_name, + .description = "Interrupt Priority Register", + .addr_offset = addr_offset, + }); + + try register_fields.append(fields.toOwnedSlice(db.arena.allocator())); + } + + try db.system_reg_addrs.put(db.gpa, base_addr + addr_offset, {}); + } + } + + const regs = try db.addRegistersToCluster(nvic, registers.items); + for (register_fields.items) |fields, i| + try db.addFieldsToRegister(regs.begin + @intCast(u32, i), fields); +} + +pub fn addScbCluster(db: *Database, scs: Database.PeripheralIndex) !void { + const scb = try db.addClusterToPeripheral(scs, .{ + .name = "SCB", + .description = "System Control Block", + .addr_offset = 0xd00, + }); + + var scb_regs = std.ArrayList(Register).init(db.gpa); + defer scb_regs.deinit(); + + try scb_regs.appendSlice(&.{ + .{ + .name = "CPUID", + .addr_offset = 0x000, + .access = .read_only, + }, + .{ + .name = "ICSR", + .description = "Interrupt Control and State Register", + .addr_offset = 0x004, + }, + .{ + .name = "AIRCR", + .description = "Application Interrupt and Reset Control Register", + .addr_offset = 0x00c, + }, + .{ + .name = "SCR", + .description = "System Control Register", + .addr_offset = 0x010, + }, + .{ + .name = "CCR", + .description = "Configuration Control Register", + .addr_offset = 0x014, + }, + .{ + .name = "SHP", + .description = "System Handlers Priority Registers. [0] is RESERVED", + .addr_offset = 0x01c, + //.dimension = .{ + // .dim = 2, + //}, + }, + .{ + .name = "SHCSR", + .description = "System Handler Control and State Register", + .addr_offset = 0x024, + }, + }); + + var regs = try db.addRegistersToCluster(scb, scb_regs.items); + + const cpuid = regs.begin; + try db.addFieldsToRegister(cpuid, &.{ + .{ .name = "REVISION", .offset = 0, .width = 4 }, + .{ .name = "PARTNO", .offset = 4, .width = 12 }, + .{ .name = "ARCHITECTURE", .offset = 16, .width = 4 }, + .{ .name = "VARIANT", .offset = 20, .width = 4 }, + .{ .name = "IMPLEMENTER", .offset = 24, .width = 8 }, + }); + + const icsr = regs.begin + 1; + try db.addFieldsToRegister(icsr, &.{ + .{ .name = "VECTACTIVE", .offset = 0, .width = 9 }, + .{ .name = "VECTPENDING", .offset = 12, .width = 9 }, + .{ .name = "ISRPENDING", .offset = 22, .width = 1 }, + .{ .name = "ISRPREEMPT", .offset = 23, .width = 1 }, + .{ .name = "PENDSTCLR", .offset = 25, .width = 1 }, + .{ .name = "PENDSTSET", .offset = 26, .width = 1 }, + .{ .name = "PENDSVCLR", .offset = 27, .width = 1 }, + .{ .name = "PENDSVSET", .offset = 28, .width = 1 }, + .{ .name = "NMIPENDSET", .offset = 31, .width = 1 }, + }); + + const aircr = regs.begin + 2; + try db.addFieldsToRegister(aircr, &.{ + .{ .name = "VECTCLRACTIVE", .offset = 1, .width = 1 }, + .{ .name = "SYSRESETREQ", .offset = 2, .width = 1 }, + .{ .name = "ENDIANESS", .offset = 15, .width = 1 }, + .{ .name = "VECTKEY", .offset = 16, .width = 16 }, + }); + + const scr = regs.begin + 3; + try db.addFieldsToRegister(scr, &.{ + .{ .name = "SLEEPONEXIT", .offset = 1, .width = 1 }, + .{ .name = "SLEEPDEEP", .offset = 2, .width = 1 }, + .{ .name = "SEVONPEND", .offset = 4, .width = 1 }, + }); + + const ccr = regs.begin + 4; + try db.addFieldsToRegister(ccr, &.{ + .{ .name = "UNALIGN_TRP", .offset = 3, .width = 1 }, + .{ .name = "STKALIGN", .offset = 9, .width = 1 }, + }); + + const shcsr = regs.begin + 6; + try db.addFieldsToRegister(shcsr, &.{ + .{ .name = "SVCALLPENDED", .offset = 15, .width = 1 }, + }); + + try db.addSystemRegisterAddresses(scs, scb, regs); +} diff --git a/tools/regz/src/cmsis/cortex_m0plus.zig b/tools/regz/src/cmsis/cortex_m0plus.zig index 84ae8af..e97f70b 100644 --- a/tools/regz/src/cmsis/cortex_m0plus.zig +++ b/tools/regz/src/cmsis/cortex_m0plus.zig @@ -1,47 +1,11 @@ const std = @import("std"); const Database = @import("../Database.zig"); const Register = @import("../Register.zig"); +const Field = @import("../Field.zig"); +const cortex_m0 = @import("cortex_m0.zig"); pub fn addCoreRegisters(db: *Database, scs: Database.PeripheralIndex) !void { - _ = db; - _ = scs; - - const nvic = try db.addClusterToPeripheral(scs, .{ - .name = "NVIC", - .description = "Nested Vectored Interrupt Controller", - .addr_offset = 0x100, - }); - - _ = try db.addRegistersToCluster(nvic, &.{ - .{ - .name = "ISER", - .description = "Interrupt Set Enable Register", - .addr_offset = 0x000, - }, - .{ - .name = "ICER", - .description = "Interrupt Clear Enable Register", - .addr_offset = 0x80, - }, - .{ - .name = "ISPR", - .description = "Interrupt Set Pending Register", - .addr_offset = 0x100, - }, - .{ - .name = "ICPR", - .description = "Interrupt Clear Pending Register", - .addr_offset = 0x180, - }, - .{ - .name = "IP", - .description = "Interrupt Priority Register", - .addr_offset = 0x300, - //.dimension = .{ - // .dim = 8, - //}, - }, - }); + try cortex_m0.addNvicCluster(db, scs); const scb = try db.addClusterToPeripheral(scs, .{ .name = "SCB", @@ -162,6 +126,8 @@ pub fn addCoreRegisters(db: *Database, scs: Database.PeripheralIndex) !void { if (db.cpu) |cpu| if (cpu.mpu_present) try addMpuRegisters(db, scs); + + try db.addSystemRegisterAddresses(scs, scb, regs); } fn addMpuRegisters(db: *Database, scs: Database.PeripheralIndex) !void { @@ -238,4 +204,6 @@ fn addMpuRegisters(db: *Database, scs: Database.PeripheralIndex) !void { .{ .name = "AP", .offset = 24, .width = 3 }, .{ .name = "XN", .offset = 28, .width = 1 }, }); + + try db.addSystemRegisterAddresses(scs, mpu, regs); } diff --git a/tools/regz/src/cmsis/cortex_m1.zig b/tools/regz/src/cmsis/cortex_m1.zig new file mode 100644 index 0000000..9e74768 --- /dev/null +++ b/tools/regz/src/cmsis/cortex_m1.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const Database = @import("../Database.zig"); +const Register = @import("../Register.zig"); +const Field = @import("../Field.zig"); +const cortex_m0 = @import("cortex_m0.zig"); + +pub fn addCoreRegisters(db: *Database, scs: Database.PeripheralIndex) !void { + try cortex_m0.addNvicCluster(db, scs); + try cortex_m0.addScbCluster(db, scs); + + const scbnscn = try db.addClusterToPeripheral(scs, .{ + .name = "SCBnSCN", + .description = "System Control and ID Register not in the SCB", + .addr_offset = 0x0, + }); + + const regs = try db.addRegistersToCluster(scbnscn, &.{ + .{ + .name = "ACTLR", + .addr_offset = 0x8, + .description = "Auxilary Control Register", + }, + }); + + const actlr = regs.begin; + try db.addFieldsToRegister(actlr, &.{ + .{ .name = "ITCMLAEN", .offset = 3, .width = 1 }, + .{ .name = "ITCMUAEN", .offset = 4, .width = 1 }, + }); +} diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 59204fc..46cf137 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -16,9 +16,9 @@ pub const Device = struct { description: ?[]const u8 = null, license_text: ?[]const u8 = null, address_unit_bits: usize, - width: usize, + width: u16, register_properties: struct { - size: ?usize = null, + size: ?u16 = null, access: ?Access = null, protection: ?[]const u8 = null, reset_value: ?u64 = null, @@ -36,11 +36,11 @@ pub const Device = struct { .description = if (xml.findValueForKey(nodes, "description")) |str| try allocator.dupe(u8, str) else null, .license_text = if (xml.findValueForKey(nodes, "licenseText")) |str| try allocator.dupe(u8, str) else null, .address_unit_bits = try std.fmt.parseInt(usize, xml.findValueForKey(nodes, "addressUnitBits") orelse return error.NoAddressUnitBits, 0), - .width = try std.fmt.parseInt(usize, xml.findValueForKey(nodes, "width") orelse return error.NoDeviceWidth, 0), + .width = try std.fmt.parseInt(u16, xml.findValueForKey(nodes, "width") orelse return error.NoDeviceWidth, 0), .register_properties = .{ // register properties group .size = if (xml.findValueForKey(nodes, "size")) |size_str| - try std.fmt.parseInt(usize, size_str, 0) + try std.fmt.parseInt(u16, size_str, 0) else null, .access = if (xml.findValueForKey(nodes, "access")) |access_str| @@ -154,7 +154,7 @@ pub const Cpu = struct { //itcm_present: bool, //dtcm_present: bool, vtor_present: bool, - nvic_prio_bits: usize, + nvic_prio_bits: u8, vendor_systick_config: bool, device_num_interrupts: ?usize, //sau_num_regions: usize, @@ -164,7 +164,10 @@ pub const Cpu = struct { .name = if (xml.findValueForKey(nodes, "name")) |name| try arena.allocator().dupe(u8, name) else null, .revision = xml.findValueForKey(nodes, "revision") orelse unreachable, .endian = try Endian.parse(xml.findValueForKey(nodes, "endian") orelse unreachable), - .nvic_prio_bits = try std.fmt.parseInt(usize, xml.findValueForKey(nodes, "nvicPrioBits") orelse unreachable, 0), + .nvic_prio_bits = if (xml.findValueForKey(nodes, "nvicPrioBits")) |nvic_prio_bits| + try std.fmt.parseInt(u8, nvic_prio_bits, 0) + else + 0, // TODO: booleans .vendor_systick_config = (try xml.parseBoolean(arena.child_allocator, nodes, "vendorSystickConfig")) orelse false, .device_num_interrupts = if (xml.findValueForKey(nodes, "deviceNumInterrupts")) |size_str| @@ -415,7 +418,7 @@ pub const Dimension = struct { }; pub const RegisterProperties = struct { - size: ?usize, + size: ?u16, access: ?Access, reset_value: ?u64, reset_mask: ?u64, @@ -423,7 +426,7 @@ pub const RegisterProperties = struct { pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !RegisterProperties { _ = arena; return RegisterProperties{ - .size = try xml.parseIntForKey(usize, arena.child_allocator, nodes, "size"), + .size = try xml.parseIntForKey(u16, 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|