add reset value and reset mask register properties (#24)

* add reset value and reset mask register properties

* usize => u64
wch-ch32v003
Matt Knight 2 years ago committed by Matt Knight
parent 3d0c1ece64
commit 780a75268f

@ -62,10 +62,14 @@ fn RegisterProperties(comptime IndexType: type) type {
/// register size in bits /// register size in bits
size: std.AutoHashMapUnmanaged(IndexType, usize) = .{}, size: std.AutoHashMapUnmanaged(IndexType, usize) = .{},
access: std.AutoHashMapUnmanaged(IndexType, Access) = .{}, 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 { fn deinit(register_properties: *@This(), allocator: Allocator) void {
register_properties.size.deinit(allocator); register_properties.size.deinit(allocator);
register_properties.access.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| if (register_properties.access) |access|
try db.register_properties.peripheral.access.put(db.gpa, peripheral_idx, 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"); var interrupt_it: ?*xml.Node = xml.findNode(peripheral_nodes, "interrupt");
while (interrupt_it != null) : (interrupt_it = xml.findNode(interrupt_it.?.next, "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_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| if (cluster_register_props.size) |size|
try db.register_properties.cluster.size.put(db.gpa, cluster_idx, 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); 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, .{ try db.clusters_in_peripherals.append(db.gpa, .{
.cluster_idx = cluster_idx, .cluster_idx = cluster_idx,
@ -336,6 +351,12 @@ fn loadRegisters(
if (register_properties.access) |access| if (register_properties.access) |access|
try db.register_properties.register.access.put(db.gpa, register_idx, 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); const field_begin_idx = @intCast(FieldIndex, db.fields.items.len);
if (xml.findNode(register_nodes, "fields")) |fields_node| { if (xml.findNode(register_nodes, "fields")) |fields_node| {
var field_it: ?*xml.Node = xml.findNode(fields_node.children, "field"); var field_it: ?*xml.Node = xml.findNode(fields_node.children, "field");
@ -443,6 +464,12 @@ fn loadNestedClusters(
if (register_properties.access) |access| if (register_properties.access) |access|
try db.register_properties.cluster.access.put(db.gpa, cluster_idx, 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, .{ try db.clusters_in_clusters.append(db.gpa, .{
.parent_idx = parent_idx, .parent_idx = parent_idx,
.child_idx = cluster_idx, .child_idx = cluster_idx,
@ -1451,12 +1478,30 @@ pub fn getRegister(
peripheral_idx, peripheral_idx,
) orelse .read_write; ) 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{ return Register{
.name = register.name, .name = register.name,
.description = register.description, .description = register.description,
.addr_offset = register.addr_offset, .addr_offset = register.addr_offset,
.size = size, .size = size,
.access = access, .access = access,
.reset_value = reset_value,
.reset_mask = reset_mask,
}; };
} }

@ -3,3 +3,5 @@ description: ?[]const u8,
addr_offset: usize, addr_offset: usize,
size: ?usize, size: ?usize,
access: ?@import("svd.zig").Access, access: ?@import("svd.zig").Access,
reset_value: ?u64,
reset_mask: ?u64,

@ -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 } else return error.NoSize, // if this shows up then we need to determine the default size of a register
// TODO: ATDF register access // TODO: ATDF register access
.access = .read_write, .access = .read_write,
// TODO: ATDF reset_value
.reset_value = null,
// TODO: ATDF reset_mask
.reset_mask = null,
}; };
} }

@ -21,8 +21,8 @@ pub const Device = struct {
size: ?usize = null, size: ?usize = null,
access: ?Access = null, access: ?Access = null,
protection: ?[]const u8 = null, protection: ?[]const u8 = null,
reset_value: ?[]const u8 = null, reset_value: ?u64 = null,
reset_mask: ?[]const u8 = null, reset_mask: ?u64 = null,
}, },
pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !Device { pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !Device {
@ -48,8 +48,14 @@ pub const Device = struct {
else else
null, null,
.protection = if (xml.findValueForKey(nodes, "protection")) |str| try allocator.dupe(u8, str) 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_value = if (xml.findValueForKey(nodes, "resetValue")) |size_str|
.reset_mask = if (xml.findValueForKey(nodes, "resetMask")) |str| try allocator.dupe(u8, str) else null, 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), .addr_offset = try std.fmt.parseInt(usize, xml.findValueForKey(nodes, "addressOffset") orelse return error.NoAddrOffset, 0),
.size = null, .size = null,
.access = .read_write, .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 { pub const RegisterProperties = struct {
size: ?usize, size: ?usize,
access: ?Access, access: ?Access,
reset_value: ?u64,
reset_mask: ?u64,
pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !RegisterProperties { pub fn parse(arena: *ArenaAllocator, nodes: *xml.Node) !RegisterProperties {
_ = arena; _ = arena;
return RegisterProperties{ return RegisterProperties{
.size = try xml.parseIntForKey(usize, arena.child_allocator, nodes, "size"), .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| .access = if (xml.findValueForKey(nodes, "access")) |access_str|
try Access.parse(access_str) try Access.parse(access_str)
else else

@ -452,7 +452,406 @@ test "field.access" {
try expectEqual(Access.read_only, db.field_access.get(0).?); try expectEqual(Access.read_only, db.field_access.get(0).?);
} }
//test "register.access" {} test "register.reset_value from device" {
// TODO: figure out if `protection` is interesting/important for us var db = try initDbFromSvd(
//test "register.reset_value" {} \\<device>
//test "register.reset_mask" {} \\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetValue>1</resetValue>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetValue>1</resetValue>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <resetValue>2</resetValue>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetValue>1</resetValue>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <cluster>
\\ <name>bruh</name>
\\ <addressOffset>0x0</addressOffset>
\\ <resetValue>2</resetValue>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </cluster>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetValue>1</resetValue>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <cluster>
\\ <name>bruh</name>
\\ <addressOffset>0x0</addressOffset>
\\ <cluster>
\\ <name>bruh2</name>
\\ <addressOffset>0x0</addressOffset>
\\ <resetValue>2</resetValue>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </cluster>
\\ </cluster>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetValue>1</resetValue>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ <size>42</size>
\\ <resetValue>2</resetValue>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetMask>0xff</resetMask>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetMask>0xff</resetMask>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <resetMask>0xffff</resetMask>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetMask>0xff</resetMask>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <cluster>
\\ <name>bruh</name>
\\ <addressOffset>0x0</addressOffset>
\\ <resetMask>0xffff</resetMask>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </cluster>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetMask>0xff</resetMask>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <cluster>
\\ <name>bruh</name>
\\ <addressOffset>0x0</addressOffset>
\\ <cluster>
\\ <name>bruh2</name>
\\ <addressOffset>0x0</addressOffset>
\\ <resetMask>0xffff</resetMask>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </cluster>
\\ </cluster>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <size>32</size>
\\ <resetMask>0xff</resetMask>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ <size>42</size>
\\ <resetMask>0xffff</resetMask>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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(
\\<device>
\\ <name>ARMCM3xxx</name>
\\ <addressUnitBits>8</addressUnitBits>
\\ <width>32</width>
\\ <peripherals>
\\ <peripheral>
\\ <name>TIMER0</name>
\\ <baseAddress>0x40010000</baseAddress>
\\ <registers>
\\ <register>
\\ <name>test</name>
\\ <addressOffset>0x0</addressOffset>
\\ </register>
\\ </registers>
\\ </peripheral>
\\ </peripherals>
\\</device>
\\
);
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.?);
}

Loading…
Cancel
Save