SVD: peripheral derivation (#84)

* SVD: peripheral derivation
wch-ch32v003
Matt Knight 2 years ago committed by Matt Knight
parent f42d279890
commit 8c47254c9c

@ -303,6 +303,8 @@ pub fn createEntity(db: *Database) EntityId {
}
pub fn destroyEntity(db: *Database, id: EntityId) void {
// note that if something can be a child, you must remove it from the child
// set of its parent
switch (db.getEntityType(id) orelse return) {
.register => {
log.debug("{}: destroying register", .{id});
@ -318,9 +320,15 @@ pub fn destroyEntity(db: *Database, id: EntityId) void {
// TODO: remove fields
_ = db.types.registers.swapRemove(id);
},
.peripheral => {
log.debug("{}: destroying peripheral", .{id});
// TODO: remove children
_ = db.types.peripherals.swapRemove(id);
},
else => {},
}
db.removeChildren(id);
db.removeAttrs(id);
}
@ -335,6 +343,22 @@ fn removeAttrs(db: *Database, id: EntityId) void {
}
}
fn removeChildren(db: *Database, id: EntityId) void {
inline for (@typeInfo(TypeOfField(Database, "children")).Struct.fields) |field| {
if (@field(db.children, field.name).fetchSwapRemove(id)) |children_entry| {
var children_set = children_entry.value;
defer children_set.deinit(db.gpa);
var it = children_set.iterator();
while (it.next()) |child_entry| {
const child_id = child_entry.key_ptr.*;
// this will get rid of the parent attr
db.destroyEntity(child_id);
}
}
}
}
pub fn createDevice(
db: *Database,
opts: struct {
@ -781,7 +805,6 @@ pub fn getEntityIdByName(
comptime var group = (tok_it.next() orelse unreachable) ++ "s";
comptime var table = (tok_it.next() orelse unreachable) ++ "s";
log.debug("group: {s}, table: {s}", .{ group, table });
var it = @field(@field(db, group), table).iterator();
return while (it.next()) |entry| {
const entry_id = entry.key_ptr.*;

@ -252,7 +252,7 @@ fn writePeripheralInstance(db: Database, instance_id: EntityId, offset: u64, out
else
"";
try writer.print("pub const {s} = @ptrCast(*volatile {s}{s}, 0x{x});\n", .{
try writer.print("pub const {s} = @intToPtr(*volatile {s}{s}, 0x{x});\n", .{
std.zig.fmtId(name),
array_prefix,
type_ref,
@ -918,7 +918,7 @@ test "gen.peripheral instantiation" {
\\pub const devices = struct {
\\ pub const TEST_DEVICE = struct {
\\ pub const peripherals = struct {
\\ pub const TEST0 = @ptrCast(*volatile types.TEST_PERIPHERAL, 0x1000);
\\ pub const TEST0 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x1000);
\\ };
\\ };
\\};
@ -950,8 +950,8 @@ test "gen.peripherals with a shared type" {
\\pub const devices = struct {
\\ pub const TEST_DEVICE = struct {
\\ pub const peripherals = struct {
\\ pub const TEST0 = @ptrCast(*volatile types.TEST_PERIPHERAL, 0x1000);
\\ pub const TEST1 = @ptrCast(*volatile types.TEST_PERIPHERAL, 0x2000);
\\ pub const TEST0 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x1000);
\\ pub const TEST1 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x2000);
\\ };
\\ };
\\};
@ -1158,8 +1158,8 @@ test "gen.namespaced register groups" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile types.PORT.PORTB, 0x23);
\\ pub const PORTC = @ptrCast(*volatile types.PORT.PORTC, 0x26);
\\ pub const PORTB = @intToPtr(*volatile types.PORT.PORTB, 0x23);
\\ pub const PORTC = @intToPtr(*volatile types.PORT.PORTC, 0x26);
\\ };
\\ };
\\};
@ -1198,7 +1198,7 @@ test "gen.peripheral with reserved register" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile types.PORTB, 0x23);
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23);
\\ };
\\ };
\\};
@ -1229,7 +1229,7 @@ test "gen.peripheral with count" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile [4]types.PORTB, 0x23);
\\ pub const PORTB = @intToPtr(*volatile [4]types.PORTB, 0x23);
\\ };
\\ };
\\};
@ -1260,7 +1260,7 @@ test "gen.peripheral with count, padding required" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile [4]types.PORTB, 0x23);
\\ pub const PORTB = @intToPtr(*volatile [4]types.PORTB, 0x23);
\\ };
\\ };
\\};
@ -1292,7 +1292,7 @@ test "gen.register with count" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile types.PORTB, 0x23);
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23);
\\ };
\\ };
\\};
@ -1323,7 +1323,7 @@ test "gen.register with count and fields" {
\\pub const devices = struct {
\\ pub const ATmega328P = struct {
\\ pub const peripherals = struct {
\\ pub const PORTB = @ptrCast(*volatile types.PORTB, 0x23);
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23);
\\ };
\\ };
\\};

@ -137,7 +137,10 @@ fn mainImpl() anyerror!void {
var buffered = std.io.bufferedWriter(raw_writer);
if (res.args.json)
try db.jsonStringify(.{}, buffered.writer())
try db.jsonStringify(
.{ .whitespace = .{ .indent = .{ .Space = 2 } } },
buffered.writer(),
)
else
try db.toZig(buffered.writer());

@ -164,7 +164,13 @@ pub fn loadIntoDb(db: *Database, doc: xml.Doc) !void {
const id = derived_entry.key_ptr.*;
const derived_name = derived_entry.value_ptr.*;
try deriveEntity(ctx.db.*, id, derived_name);
deriveEntity(ctx, id, derived_name) catch |err| {
log.warn("failed to derive entity {} from {s}: {}", .{
id,
derived_name,
err,
});
};
}
db.assertValid();
@ -225,10 +231,43 @@ fn archFromStr(str: []const u8) Database.Arch {
.unknown;
}
pub fn deriveEntity(db: Database, id: EntityId, derived_name: []const u8) !void {
pub fn deriveEntity(ctx: Context, id: EntityId, derived_name: []const u8) !void {
const db = ctx.db;
log.debug("{}: derived from {s}", .{ id, derived_name });
const entity_type = db.getEntityType(id);
assert(entity_type != null);
switch (entity_type.?) {
.peripheral => {
// TODO: what do we do when we have other fields set? maybe make
// some assertions and then skip if we're not sure
const name = db.attrs.name.get(id);
const base_instance_id = try db.getEntityIdByName("instance.peripheral", derived_name);
const base_id = db.instances.peripherals.get(base_instance_id) orelse return error.PeripheralNotFound;
if (ctx.derived_entities.contains(base_id)) {
log.warn("TODO: chained peripheral derivation: {?s}", .{name});
return error.TodoChainedDerivation;
}
if (try db.instances.peripherals.fetchPut(db.gpa, id, base_id)) |entry| {
const maybe_remove_peripheral_id = entry.value;
var it = db.instances.peripherals.iterator();
while (it.next()) |instance_entry| {
const used_peripheral_id = instance_entry.value_ptr.*;
// if there is a match don't delete the entity
if (used_peripheral_id == maybe_remove_peripheral_id)
break;
} else {
// no instance is using this peripheral so we can remove it
db.destroyEntity(maybe_remove_peripheral_id);
}
}
},
else => {
log.warn("TODO: implement derivation for {?}", .{entity_type});
},
}
}
pub fn loadPeripheral(ctx: *Context, node: xml.Node, device_id: EntityId) !void {

Loading…
Cancel
Save