Nvic codegen (#41)

* add system registers for cortex m0 and m1, nvic register generation for the chip

* make warning log a debug log

* usize to u64

* register size is now max 2^16 - 1
wch-ch32v003
Matt Knight 2 years ago committed by Matt Knight
parent c38ca6403e
commit 48f2c0b051

@ -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);
{
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) = .{},

@ -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(),

@ -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,

@ -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);

@ -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 {

@ -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);
}

@ -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);
}

@ -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 },
});
}

@ -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|

Loading…
Cancel
Save