update json tree api (#89)

* update json tree api

* sneak in namespacing of types into peripherals, registers, etc

* fix cache api usage, later try cache invalidation
wch-ch32v003
Matt Knight 2 years ago committed by Matt Knight
parent f174713fd3
commit 060b6fbd5a

@ -73,8 +73,7 @@ pub const Regz = struct {
// TODO: improve collision resistance // TODO: improve collision resistance
const basename = std.fs.path.basename(schema_path); const basename = std.fs.path.basename(schema_path);
const extension = std.fs.path.extension(basename); const extension = std.fs.path.extension(basename);
const destination_path = std.fs.path.join(regz.builder.allocator, &.{ const destination_path = regz.builder.cache_root.join(regz.builder.allocator, &.{
regz.builder.cache_root,
"regz", "regz",
std.mem.join(regz.builder.allocator, "", &.{ std.mem.join(regz.builder.allocator, "", &.{
basename[0 .. basename.len - extension.len], basename[0 .. basename.len - extension.len],

@ -180,7 +180,11 @@ fn typesReference(db: Database, type_id: EntityId) ![]const u8 {
defer full_name_components.deinit(); defer full_name_components.deinit();
var id = type_id; var id = type_id;
while (true) {
// hard limit for walking up the tree, if we hit it there's a bug
const count_max: u32 = 8;
var count: u32 = 0;
while (count < count_max) : (count += 1) {
if (db.attrs.name.get(id)) |next_name| if (db.attrs.name.get(id)) |next_name|
try full_name_components.insert(0, next_name) try full_name_components.insert(0, next_name)
else else
@ -190,7 +194,7 @@ fn typesReference(db: Database, type_id: EntityId) ![]const u8 {
id = parent_id id = parent_id
else else
break; break;
} } else @panic("hit limit for reference length");
if (full_name_components.items.len == 0) if (full_name_components.items.len == 0)
return error.CantReference; return error.CantReference;
@ -198,6 +202,16 @@ fn typesReference(db: Database, type_id: EntityId) ![]const u8 {
var full_name = std.ArrayList(u8).init(db.arena.allocator()); var full_name = std.ArrayList(u8).init(db.arena.allocator());
const writer = full_name.writer(); const writer = full_name.writer();
try writer.writeAll("types"); try writer.writeAll("types");
// determine the namespace under 'types' the reference is under
const root_parent_entity_type = db.getEntityType(id).?;
inline for (@typeInfo(Database.EntityType).Enum.fields) |field| {
if (root_parent_entity_type == @field(Database.EntityType, field.name)) {
try writer.print(".{s}s", .{field.name});
break;
}
}
for (full_name_components.items) |component| for (full_name_components.items) |component|
try writer.print(".{s}", .{ try writer.print(".{s}", .{
std.zig.fmtId(component), std.zig.fmtId(component),
@ -290,16 +304,22 @@ fn writeTypes(db: Database, writer: anytype) !void {
\\ \\
); );
// TODO: order the peripherals alphabetically? if (db.types.peripherals.count() > 0) {
var it = db.types.peripherals.iterator(); try writer.writeAll("pub const peripherals = struct {\n");
while (it.next()) |entry| {
const peripheral_id = entry.key_ptr.*; // TODO: order the peripherals alphabetically?
writePeripheral(db, peripheral_id, writer) catch |err| { var it = db.types.peripherals.iterator();
log.warn("failed to generate peripheral '{s}': {}", .{ while (it.next()) |entry| {
db.attrs.name.get(peripheral_id) orelse "<unknown>", const peripheral_id = entry.key_ptr.*;
err, writePeripheral(db, peripheral_id, writer) catch |err| {
}); log.warn("failed to generate peripheral '{s}': {}", .{
}; db.attrs.name.get(peripheral_id) orelse "<unknown>",
err,
});
};
}
try writer.writeAll("};\n");
} }
try writer.writeAll("};\n"); try writer.writeAll("};\n");
@ -892,11 +912,13 @@ test "gen.peripheral type with register and field" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ TEST_REGISTER: mmio.Mmio(packed struct(u32) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_FIELD: u1, \\ TEST_REGISTER: mmio.Mmio(packed struct(u32) {
\\ padding: u31, \\ TEST_FIELD: u1,
\\ }), \\ padding: u31,
\\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -918,17 +940,19 @@ test "gen.peripheral instantiation" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const TEST_DEVICE = struct { \\ pub const TEST_DEVICE = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const TEST0 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x1000); \\ pub const TEST0 = @intToPtr(*volatile types.peripherals.TEST_PERIPHERAL, 0x1000);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ TEST_REGISTER: mmio.Mmio(packed struct(u32) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_FIELD: u1, \\ TEST_REGISTER: mmio.Mmio(packed struct(u32) {
\\ padding: u31, \\ TEST_FIELD: u1,
\\ }), \\ padding: u31,
\\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -950,18 +974,20 @@ test "gen.peripherals with a shared type" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const TEST_DEVICE = struct { \\ pub const TEST_DEVICE = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const TEST0 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x1000); \\ pub const TEST0 = @intToPtr(*volatile types.peripherals.TEST_PERIPHERAL, 0x1000);
\\ pub const TEST1 = @intToPtr(*volatile types.TEST_PERIPHERAL, 0x2000); \\ pub const TEST1 = @intToPtr(*volatile types.peripherals.TEST_PERIPHERAL, 0x2000);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ TEST_REGISTER: mmio.Mmio(packed struct(u32) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_FIELD: u1, \\ TEST_REGISTER: mmio.Mmio(packed struct(u32) {
\\ padding: u31, \\ TEST_FIELD: u1,
\\ }), \\ padding: u31,
\\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -981,45 +1007,47 @@ test "gen.peripheral with modes" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern union { \\ pub const peripherals = struct {
\\ pub const Mode = enum { \\ pub const TEST_PERIPHERAL = extern union {
\\ TEST_MODE1, \\ pub const Mode = enum {
\\ TEST_MODE2, \\ TEST_MODE1,
\\ }; \\ TEST_MODE2,
\\ };
\\ \\
\\ pub fn getMode(self: *volatile @This()) Mode { \\ pub fn getMode(self: *volatile @This()) Mode {
\\ { \\ {
\\ const value = self.TEST_MODE1.COMMON_REGISTER.read().TEST_FIELD; \\ const value = self.TEST_MODE1.COMMON_REGISTER.read().TEST_FIELD;
\\ switch (value) { \\ switch (value) {
\\ 0 => return .TEST_MODE1, \\ 0 => return .TEST_MODE1,
\\ else => {}, \\ else => {},
\\ }
\\ } \\ }
\\ } \\ {
\\ { \\ const value = self.TEST_MODE2.COMMON_REGISTER.read().TEST_FIELD;
\\ const value = self.TEST_MODE2.COMMON_REGISTER.read().TEST_FIELD; \\ switch (value) {
\\ switch (value) { \\ 1 => return .TEST_MODE2,
\\ 1 => return .TEST_MODE2, \\ else => {},
\\ else => {}, \\ }
\\ } \\ }
\\ }
\\ \\
\\ unreachable; \\ unreachable;
\\ } \\ }
\\ \\
\\ TEST_MODE1: extern struct { \\ TEST_MODE1: extern struct {
\\ TEST_REGISTER1: u32, \\ TEST_REGISTER1: u32,
\\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) { \\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) {
\\ TEST_FIELD: u1, \\ TEST_FIELD: u1,
\\ padding: u31, \\ padding: u31,
\\ }), \\ }),
\\ }, \\ },
\\ TEST_MODE2: extern struct { \\ TEST_MODE2: extern struct {
\\ TEST_REGISTER2: u32, \\ TEST_REGISTER2: u32,
\\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) { \\ COMMON_REGISTER: mmio.Mmio(packed struct(u32) {
\\ TEST_FIELD: u1, \\ TEST_FIELD: u1,
\\ padding: u31, \\ padding: u31,
\\ }), \\ }),
\\ }, \\ },
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1039,14 +1067,16 @@ test "gen.peripheral with enum" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ pub const TEST_ENUM = enum(u4) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_ENUM_FIELD1 = 0x0, \\ pub const TEST_ENUM = enum(u4) {
\\ TEST_ENUM_FIELD2 = 0x1, \\ TEST_ENUM_FIELD1 = 0x0,
\\ _, \\ TEST_ENUM_FIELD2 = 0x1,
\\ }; \\ _,
\\ };
\\ \\
\\ TEST_REGISTER: u8, \\ TEST_REGISTER: u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1066,13 +1096,15 @@ test "gen.peripheral with enum, enum is exhausted of values" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ pub const TEST_ENUM = enum(u1) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_ENUM_FIELD1 = 0x0, \\ pub const TEST_ENUM = enum(u1) {
\\ TEST_ENUM_FIELD2 = 0x1, \\ TEST_ENUM_FIELD1 = 0x0,
\\ }; \\ TEST_ENUM_FIELD2 = 0x1,
\\ };
\\ \\
\\ TEST_REGISTER: u8, \\ TEST_REGISTER: u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1092,20 +1124,22 @@ test "gen.field with named enum" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ pub const TEST_ENUM = enum(u4) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_ENUM_FIELD1 = 0x0, \\ pub const TEST_ENUM = enum(u4) {
\\ TEST_ENUM_FIELD2 = 0x1, \\ TEST_ENUM_FIELD1 = 0x0,
\\ _, \\ TEST_ENUM_FIELD2 = 0x1,
\\ }; \\ _,
\\ };
\\ \\
\\ TEST_REGISTER: mmio.Mmio(packed struct(u8) { \\ TEST_REGISTER: mmio.Mmio(packed struct(u8) {
\\ TEST_FIELD: packed union { \\ TEST_FIELD: packed union {
\\ raw: u4, \\ raw: u4,
\\ value: TEST_ENUM, \\ value: TEST_ENUM,
\\ }, \\ },
\\ padding: u4, \\ padding: u4,
\\ }), \\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1125,18 +1159,20 @@ test "gen.field with anonymous enum" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const TEST_PERIPHERAL = extern struct { \\ pub const peripherals = struct {
\\ TEST_REGISTER: mmio.Mmio(packed struct(u8) { \\ pub const TEST_PERIPHERAL = extern struct {
\\ TEST_FIELD: packed union { \\ TEST_REGISTER: mmio.Mmio(packed struct(u8) {
\\ raw: u4, \\ TEST_FIELD: packed union {
\\ value: enum(u4) { \\ raw: u4,
\\ TEST_ENUM_FIELD1 = 0x0, \\ value: enum(u4) {
\\ TEST_ENUM_FIELD2 = 0x1, \\ TEST_ENUM_FIELD1 = 0x0,
\\ _, \\ TEST_ENUM_FIELD2 = 0x1,
\\ _,
\\ },
\\ }, \\ },
\\ }, \\ padding: u4,
\\ padding: u4, \\ }),
\\ }), \\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1158,24 +1194,26 @@ test "gen.namespaced register groups" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile types.PORT.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile types.peripherals.PORT.PORTB, 0x23);
\\ pub const PORTC = @intToPtr(*volatile types.PORT.PORTC, 0x26); \\ pub const PORTC = @intToPtr(*volatile types.peripherals.PORT.PORTC, 0x26);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORT = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = extern struct { \\ pub const PORT = struct {
\\ PORTB: u8, \\ pub const PORTB = extern struct {
\\ DDRB: u8, \\ PORTB: u8,
\\ PINB: u8, \\ DDRB: u8,
\\ }; \\ PINB: u8,
\\ };
\\ \\
\\ pub const PORTC = extern struct { \\ pub const PORTC = extern struct {
\\ PORTC: u8, \\ PORTC: u8,
\\ DDRC: u8, \\ DDRC: u8,
\\ PINC: u8, \\ PINC: u8,
\\ };
\\ }; \\ };
\\ }; \\ };
\\}; \\};
@ -1198,16 +1236,18 @@ test "gen.peripheral with reserved register" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile types.peripherals.PORTB, 0x23);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: u32, \\ pub const PORTB = extern struct {
\\ reserved8: [4]u8, \\ PORTB: u32,
\\ PINB: u32, \\ reserved8: [4]u8,
\\ PINB: u32,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1229,16 +1269,18 @@ test "gen.peripheral with count" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile [4]types.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile [4]types.peripherals.PORTB, 0x23);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: u8, \\ pub const PORTB = extern struct {
\\ DDRB: u8, \\ PORTB: u8,
\\ PINB: u8, \\ DDRB: u8,
\\ PINB: u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1260,17 +1302,19 @@ test "gen.peripheral with count, padding required" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile [4]types.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile [4]types.peripherals.PORTB, 0x23);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: u8, \\ pub const PORTB = extern struct {
\\ DDRB: u8, \\ PORTB: u8,
\\ PINB: u8, \\ DDRB: u8,
\\ padding: [1]u8, \\ PINB: u8,
\\ padding: [1]u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1292,16 +1336,18 @@ test "gen.register with count" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile types.peripherals.PORTB, 0x23);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: [4]u8, \\ pub const PORTB = extern struct {
\\ DDRB: u8, \\ PORTB: [4]u8,
\\ PINB: u8, \\ DDRB: u8,
\\ PINB: u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1323,19 +1369,21 @@ test "gen.register with count and fields" {
\\pub const devices = struct { \\pub const devices = struct {
\\ pub const ATmega328P = struct { \\ pub const ATmega328P = struct {
\\ pub const peripherals = struct { \\ pub const peripherals = struct {
\\ pub const PORTB = @intToPtr(*volatile types.PORTB, 0x23); \\ pub const PORTB = @intToPtr(*volatile types.peripherals.PORTB, 0x23);
\\ }; \\ };
\\ }; \\ };
\\}; \\};
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: [4]mmio.Mmio(packed struct(u8) { \\ pub const PORTB = extern struct {
\\ TEST_FIELD: u4, \\ PORTB: [4]mmio.Mmio(packed struct(u8) {
\\ padding: u4, \\ TEST_FIELD: u4,
\\ }), \\ padding: u4,
\\ DDRB: u8, \\ }),
\\ PINB: u8, \\ DDRB: u8,
\\ PINB: u8,
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1355,12 +1403,14 @@ test "gen.field with count, width of one, offset, and padding" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: mmio.Mmio(packed struct(u8) { \\ pub const PORTB = extern struct {
\\ reserved2: u2, \\ PORTB: mmio.Mmio(packed struct(u8) {
\\ TEST_FIELD: packed struct(u5) { u1, u1, u1, u1, u1 }, \\ reserved2: u2,
\\ padding: u1, \\ TEST_FIELD: packed struct(u5) { u1, u1, u1, u1, u1 },
\\ }), \\ padding: u1,
\\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\
@ -1380,12 +1430,14 @@ test "gen.field with count, multi-bit width, offset, and padding" {
\\const mmio = micro.mmio; \\const mmio = micro.mmio;
\\ \\
\\pub const types = struct { \\pub const types = struct {
\\ pub const PORTB = extern struct { \\ pub const peripherals = struct {
\\ PORTB: mmio.Mmio(packed struct(u8) { \\ pub const PORTB = extern struct {
\\ reserved2: u2, \\ PORTB: mmio.Mmio(packed struct(u8) {
\\ TEST_FIELD: packed struct(u4) { u2, u2 }, \\ reserved2: u2,
\\ padding: u2, \\ TEST_FIELD: packed struct(u4) { u2, u2 },
\\ }), \\ padding: u2,
\\ }),
\\ };
\\ }; \\ };
\\}; \\};
\\ \\

@ -602,7 +602,10 @@ fn loadPeripheralInstance(
} }
pub fn toJson(db: Database) !json.ValueTree { pub fn toJson(db: Database) !json.ValueTree {
var arena = ArenaAllocator.init(db.gpa); const arena = try db.gpa.create(ArenaAllocator);
errdefer db.gpa.destroy(arena);
arena.* = ArenaAllocator.init(db.gpa);
errdefer arena.deinit(); errdefer arena.deinit();
const allocator = arena.allocator(); const allocator = arena.allocator();
@ -614,13 +617,13 @@ pub fn toJson(db: Database) !json.ValueTree {
while (device_it.next()) |entry| while (device_it.next()) |entry|
try populateDevice( try populateDevice(
db, db,
&arena, arena,
&devices, &devices,
entry.key_ptr.*, entry.key_ptr.*,
); );
try root.put("version", .{ .String = schema_version }); try root.put("version", .{ .String = schema_version });
try populateTypes(db, &arena, &types); try populateTypes(db, arena, &types);
if (types.count() > 0) if (types.count() > 0)
try root.put("types", .{ .Object = types }); try root.put("types", .{ .Object = types });

Loading…
Cancel
Save