From 7c75bc6297438dbe2818081e00bcdc4b274b9255 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Thu, 2 Mar 2023 00:32:21 -0800 Subject: [PATCH] don't generate system registers (#96) * don't generate system registers * handle missing cpu name --- tools/regz/src/arch/arm.zig | 95 +++++----- tools/regz/src/arch/arm/nvic.zig | 159 ++++++++++++++++ tools/regz/src/svd.zig | 111 +++++------- tools/regz/src/svd/cmsis.zig | 99 ---------- tools/regz/src/svd/cmsis/cortex_m0.zig | 199 --------------------- tools/regz/src/svd/cmsis/cortex_m0plus.zig | 187 ------------------- tools/regz/src/svd/cmsis/cortex_m1.zig | 30 ---- 7 files changed, 252 insertions(+), 628 deletions(-) create mode 100644 tools/regz/src/arch/arm/nvic.zig delete mode 100644 tools/regz/src/svd/cmsis.zig delete mode 100644 tools/regz/src/svd/cmsis/cortex_m0.zig delete mode 100644 tools/regz/src/svd/cmsis/cortex_m0plus.zig delete mode 100644 tools/regz/src/svd/cmsis/cortex_m1.zig diff --git a/tools/regz/src/arch/arm.zig b/tools/regz/src/arch/arm.zig index a6bc7c2..8b69dfb 100644 --- a/tools/regz/src/arch/arm.zig +++ b/tools/regz/src/arch/arm.zig @@ -10,42 +10,52 @@ const gen = @import("../gen.zig"); const InterruptWithIndexAndName = @import("InterruptWithIndexAndName.zig"); const Interrupt = @import("Interrupt.zig"); +const svd = @import("../svd.zig"); + const log = std.log.scoped(.@"gen.arm"); // it's intended that these interrupts are added to the database in the // different front-ends. This way this information is serialized for // tooling -pub const system_interrupts = struct { - pub const cortex_m0 = [_]Interrupt{ - Interrupt{ .name = "NMI", .index = -14 }, - Interrupt{ .name = "HardFault", .index = -13 }, - Interrupt{ .name = "SVCall", .index = -5 }, - Interrupt{ .name = "PendSV", .index = -2 }, - }; + +const system_interrupts = struct { + // zig fmt: off + const nmi = Interrupt{ .index = -14, .name = "NMI" }; + const hard_fault = Interrupt{ .index = -13, .name = "HardFault" }; + const mem_manage = Interrupt{ .index = -12, .name = "MemManageFault" }; + const bus_fault = Interrupt{ .index = -11, .name = "BusFault" }; + const usage_fault = Interrupt{ .index = -10, .name = "UsageFault" }; + const secure_fault = Interrupt{ .index = -9, .name = "SecureFault" }; + const svcall = Interrupt{ .index = -5, .name = "SVCall" }; + const debug_monitor = Interrupt{ .index = -4, .name = "DebugMonitor" }; + const pendsv = Interrupt{ .index = -2, .name = "PendSV" }; + const systick = Interrupt{ .index = -1, .name = "SysTick" }; + // zig fmt: on + + pub const cortex_m0 = [_]Interrupt{ nmi, hard_fault, svcall, pendsv }; pub const cortex_m0plus = cortex_m0; - pub const cortex_m3 = [_]Interrupt{ - Interrupt{ .name = "MemManageFault", .index = -12 }, - Interrupt{ .name = "BusFault", .index = -11 }, - Interrupt{ .name = "UsageFault", .index = -10 }, - Interrupt{ .name = "DebugMonitor", .index = -4 }, - } ++ cortex_m0; + pub const cortex_m1 = cortex_m0; + pub const cortex_m23 = cortex_m0; + + pub const cortex_m3 = [_]Interrupt{ nmi, hard_fault, mem_manage, bus_fault, usage_fault, svcall, pendsv }; pub const cortex_m4 = cortex_m3; + pub const cortex_m7 = cortex_m3; + + pub const cortex_m33 = [_]Interrupt{ nmi, hard_fault, mem_manage, bus_fault, usage_fault, secure_fault, svcall, debug_monitor, pendsv }; + // The m35p was announced in 2018 and the technical reference manual does + // not list the exceptions. It has been described as an m33 with some + // upgrades, so I'm going give it the same exceptions + pub const cortex_m35p = cortex_m33; + // The m55 was announced in 2020 and I have about the same amount of information as the m35p + pub const cortex_m55 = cortex_m33; }; -pub fn load_systick_interrupt(db: *Database, device_id: EntityId) !void { - _ = try db.create_interrupt(device_id, .{ - .name = "SysTick", - .index = -1, - // TODO: description - }); -} - pub fn load_system_interrupts(db: *Database, device_id: EntityId) !void { - const arch = db.instances.devices.get(device_id).?.arch; - assert(arch.is_arm()); + const device = db.instances.devices.get(device_id).?; + assert(device.arch.is_arm()); inline for (@typeInfo(Database.Arch).Enum.fields) |field| { - if (arch == @field(Database.Arch, field.name)) { + if (device.arch == @field(Database.Arch, field.name)) { if (@hasDecl(system_interrupts, field.name)) { for (@field(system_interrupts, field.name)) |interrupt| { _ = try db.create_interrupt(device_id, .{ @@ -59,7 +69,19 @@ pub fn load_system_interrupts(db: *Database, device_id: EntityId) !void { break; } } else { - log.warn("TODO: system interrupts handlers for {}", .{arch}); + log.warn("TODO: system interrupts handlers for {}", .{device.arch}); + } + + const vendor_systick_config = if (device.properties.get("cpu.vendorSystickConfig")) |str| + try svd.parse_bool(str) + else + false; + + if (!vendor_systick_config) { + _ = try db.create_interrupt(device_id, .{ + .name = system_interrupts.systick.name, + .index = system_interrupts.systick.index, + }); } } @@ -72,25 +94,6 @@ pub fn write_interrupt_vector( const arch = db.instances.devices.get(device_id).?.arch; assert(arch.is_arm()); - switch (arch) { - // the basic vector table below should be fine for cortex-m - .cortex_m0, - .cortex_m0plus, - .cortex_m1, - .cortex_m23, - .cortex_m3, - .cortex_m33, - .cortex_m35p, - .cortex_m4, - .cortex_m55, - .cortex_m7, - => {}, - else => { - log.warn("TODO: exception handlers for {}", .{arch}); - return; - }, - } - try writer.writeAll( \\pub const VectorTable = extern struct { \\ const Handler = micro.interrupt.Handler; @@ -118,10 +121,6 @@ pub fn write_interrupt_vector( }); } - switch (arch) { - else => log.warn("TODO: exception handlers for {}", .{arch}), - } - std.sort.sort( InterruptWithIndexAndName, interrupts.items, diff --git a/tools/regz/src/arch/arm/nvic.zig b/tools/regz/src/arch/arm/nvic.zig new file mode 100644 index 0000000..5a781da --- /dev/null +++ b/tools/regz/src/arch/arm/nvic.zig @@ -0,0 +1,159 @@ +//! NVIC Registers +//! +//! ╔════════╦══════════╦═══╦═══╦═══════╦══════╦════════╦══════════════════════════════════╦═╦════╦═════╦════╦═════╦════╦════╦═════╦═════╦══════╦═════╦══════════╦══════════╦═══════╦════════╗ +//! ║ Offset ║ Register ║ R ║ W ║ Field ║ With ║ Offset ║ Description ║ ║ M0 ║ M0+ ║ M1 ║ M3 ║ M4 ║ M7 ║ M23 ║ M33 ║ M35P ║ M55 ║ ARMV8MBL ║ ARMV8MML ║ SC000 ║ SC3000 ║ +//! ╠════════╬══════════╬═══╬═══╬═══════╬══════╬════════╬══════════════════════════════════╬═╬════╩═════╩════╩═════╩════╩════╩═════╩═════╩══════╩═════╩══════════╩══════════╩═══════╩════════╣ +//! ║ 0x0000 ║ ISER ║ X ║ X ║ ║ ║ ║ Interrupt Set Enable Register ║ ║ X X X X ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0080 ║ ICER ║ X ║ X ║ ║ ║ ║ Interrupt Clear Enable Register ║ ║ X X X X ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0100 ║ ISPR ║ X ║ X ║ ║ ║ ║ Interrupt Set Pending Register ║ ║ X X X X ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0180 ║ ICPR ║ X ║ X ║ ║ ║ ║ Interrupt Clear Pending Register ║ ║ X X X X ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0200 ║ IABR ║ ║ ║ ║ ║ ║ Interrupt Priority Register ║ ║ 8 ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0300 ║ IP ║ X ║ X ║ ║ ║ ║ ║ ║ 8 8 8 240 ? ? ? ? ? ? ? ? ? ? ║ +//! ║ 0x0E00 ║ STIR ║ ║ ║ ║ ║ ║ ║ ║ X ? ? ? ? ? ? ? ? ? ? ║ +//! ║ ║ ║ ║ ║ INTID ║ 9 ║ 0 ║ ║ ║ X ? ? ? ? ? ? ? ? ? ? ║ +//! ╚════════╩══════════╩═══╩═══╩═══════╩══════╩════════╩══════════════════════════════════╩═╩═══════════════════════════════════════════════════════════════════════════════════════════════╝ + +const std = @import("std"); +const Database = @import("../../Database.zig"); +const EntityId = Database.EntityId; + +pub const address = 0xe000e100; + +// deletes an existing NVIC peripheral if it has one. This is because the +// registers we'll generate are better :) +// +// assumes if the device has interrupts, they've been loaded +pub fn load(db: *Database, device_id: EntityId) !void { + const device = db.instances.devices.get(device_id).?; + if (!device.arch.is_arm()) + return; + + switch (device.arch) { + .cortex_m0, .cortex_m0plus, .cortex_m1 => {}, + else => { + std.log.warn("TODO: implement NVIC register generation for '{}'", .{device.arch}); + return; + }, + } + + const nvic = try db.create_peripheral(.{ + .name = "NVIC", + .description = "Nested Vectored Interrupt Controller", + }); + + _ = try db.create_peripheral_instance(device_id, nvic, .{ + .name = "NVIC", + .offset = address, + }); + + // TODO: behavior is different for cortex-m3/4/7, probably the others too + const interrupt_registers = [_]EntityId{ + try db.create_register(nvic, .{ .name = "ISER", .offset = 0x000, .size = 32, .description = "Interrupt Set Enable Register" }), + try db.create_register(nvic, .{ .name = "ICER", .offset = 0x080, .size = 32, .description = "Interrupt Clear Enable Register" }), + try db.create_register(nvic, .{ .name = "ISPR", .offset = 0x100, .size = 32, .description = "Interrupt Set Pending Register" }), + try db.create_register(nvic, .{ .name = "ICPR", .offset = 0x180, .size = 32, .description = "Interrupt Clear Pending Register" }), + }; + + // TODO: generate IP if any of the above fail, like nvicPrioBits is missing + + // interrupt priority registers + if (device.properties.get("cpu.nvicPrioBits")) |bits| if (try std.fmt.parseInt(u32, bits, 10) > 0) { + const ip_addr_offset = 0x300; + + var i: u32 = 0; + while (i < 8) : (i += 1) { + const addr_offset = ip_addr_offset + (i * 4); + const reg_name = try std.fmt.allocPrint(db.arena.allocator(), "IP{}", .{i}); + + _ = try db.create_register(nvic, .{ + .name = reg_name, + .description = "Interrupt Priority Register", + .offset = addr_offset, + .size = 32, + }); + } + }; + + // fields for basic registers + const interrupts = db.instances.interrupts; + for (interrupts.keys(), interrupts.values()) |interrupt_id, interrupt_index| { + if (interrupt_index < 0) + continue; + + const interrupt_name = db.attrs.name.get(interrupt_id).?; + for (interrupt_registers) |register| { + _ = try db.create_field(register, .{ + .name = interrupt_name, + .offset = @bitCast(u32, interrupt_index), + .size = 1, + }); + } + + const nvic_prio_bits = try std.fmt.parseInt( + u32, + device.properties.get("cpu.nvicPrioBits") orelse return error.MissingNvicPrioBits, + 10, + ); + if (nvic_prio_bits == 0) continue; + + const reg_name = try std.fmt.allocPrint(db.arena.allocator(), "IP{}", .{interrupt_index >> 2}); + const reg_id = try db.get_entity_id_by_name("type.register", reg_name); + _ = try db.create_field(reg_id, .{ + .name = interrupt_name, + .offset = (8 * (@intCast(u8, interrupt_index) % 4)) + (8 - nvic_prio_bits), + .size = nvic_prio_bits, + }); + } + + // TODO: cpu module specific NVIC registers + + // destroy registers that line up with NVIC registers + var unique_peripherals = std.ArrayList(EntityId).init(db.gpa); + defer unique_peripherals.deinit(); + + for (db.types.peripherals.keys()) |peripheral_id| outer: { + var unique_instance_id: ?EntityId = null; + const instances = db.instances.peripherals; + for (instances.keys(), instances.values()) |instance_id, type_id| { + if (type_id == peripheral_id) { + if (type_id == nvic) + break :outer; + + if (unique_instance_id == null) { + unique_instance_id = instance_id; + } else break :outer; + } + } + + // every peripheral type should have an instance + try unique_peripherals.append(unique_instance_id.?); + } + + // Put together a hit list of register addresses + var hit_list = std.AutoArrayHashMap(u64, void).init(db.gpa); + defer hit_list.deinit(); + + for (db.children.registers.get(nvic).?.keys()) |child_id| { + if (db.attrs.offset.get(child_id)) |register_offset| { + std.log.debug("hit_list entry: 0x{x}", .{address + register_offset}); + try hit_list.put(address + register_offset, {}); + } + } + + var destroy_list = std.AutoArrayHashMap(EntityId, void).init(db.gpa); + defer destroy_list.deinit(); + + for (unique_peripherals.items) |instance_id| { + const peripheral_id = db.instances.peripherals.get(instance_id).?; + const instance_offset = db.attrs.offset.get(instance_id).?; + const children = db.children.registers.get(peripheral_id) orelse continue; + for (children.keys()) |register_id| { + const register_offset = db.attrs.offset.get(register_id) orelse continue; + if (hit_list.contains(instance_offset + register_offset)) + try destroy_list.put(register_id, {}); + } + } + + for (destroy_list.keys()) |register_id| + db.destroy_entity(register_id); +} diff --git a/tools/regz/src/svd.zig b/tools/regz/src/svd.zig index 55ea43d..b615b7f 100644 --- a/tools/regz/src/svd.zig +++ b/tools/regz/src/svd.zig @@ -5,7 +5,6 @@ const assert = std.debug.assert; const xml = @import("xml.zig"); const arm = @import("arch/arm.zig"); -const cmsis = @import("svd/cmsis.zig"); const Database = @import("Database.zig"); const EntityId = Database.EntityId; @@ -52,6 +51,10 @@ const svd_boolean = std.ComptimeStringMap(bool, .{ .{ "0", false }, }); +pub fn parse_bool(str: []const u8) !bool { + return svd_boolean.get(str) orelse error.InvalidSvdBoolean; +} + pub fn load_into_db(db: *Database, doc: xml.Doc) !void { const root = try doc.get_root_element(); @@ -83,75 +86,50 @@ pub fn load_into_db(db: *Database, doc: xml.Doc) !void { var cpu_it = root.iterate(&.{}, "cpu"); if (cpu_it.next()) |cpu| { - const cpu_name = cpu.get_value("name") orelse return error.MissingCpuName; - const cpu_revision = cpu.get_value("revision") orelse return error.MissingCpuRevision; - const nvic_prio_bits = cpu.get_value("nvicPrioBits") orelse return error.MissingNvicPrioBits; - const vendor_systick_config = cpu.get_value("vendorSystickConfig") orelse return error.MissingVendorSystickConfig; - - const arch = arch_from_str(cpu_name); - db.instances.devices.getEntry(device_id).?.value_ptr.arch = arch; - if (arch.is_arm()) - try arm.load_system_interrupts(db, device_id); - - // TODO: is this the right logic? - if (svd_boolean.get(vendor_systick_config)) |systick| { - if (!systick) - try arm.load_systick_interrupt(db, device_id); - } else { - try arm.load_systick_interrupt(db, device_id); - } - - // TODO: - - // cpu name => arch - try db.add_device_property(device_id, "cpu.name", cpu_name); - try db.add_device_property(device_id, "cpu.revision", cpu_revision); - try db.add_device_property(device_id, "cpu.nvic_prio_bits", nvic_prio_bits); - try db.add_device_property(device_id, "cpu.vendor_systick_config", vendor_systick_config); - - if (cpu.get_value("endian")) |endian| - try db.add_device_property(device_id, "cpu.endian", endian); - - if (cpu.get_value("mpuPresent")) |mpu| - try db.add_device_property(device_id, "cpu.mpu", mpu); - - if (cpu.get_value("fpuPresent")) |fpu| - try db.add_device_property(device_id, "cpu.fpu", fpu); - - if (cpu.get_value("dspPresent")) |dsp| - try db.add_device_property(device_id, "cpu.dsp", dsp); - - if (cpu.get_value("icachePresent")) |icache| - try db.add_device_property(device_id, "cpu.icache", icache); - - if (cpu.get_value("dcachePresent")) |dcache| - try db.add_device_property(device_id, "cpu.dcache", dcache); - - if (cpu.get_value("itcmPresent")) |itcm| - try db.add_device_property(device_id, "cpu.itcm", itcm); + const required_properties: []const []const u8 = &.{ + "name", + "revision", + "endian", + "nvicPrioBits", + }; - if (cpu.get_value("dtcmPresent")) |dtcm| - try db.add_device_property(device_id, "cpu.dtcm", dtcm); + const optional_properties: []const []const u8 = &.{ + "vendorSystickConfig", + "mpuPresent", + "fpuPresent", + "dspPresent", + "icachePresent", + "dcachePresent", + "itcmPresent", + "dtcmPresent", + "vtorPresent", + "deviceNumInterrupts", + "fpuDP", + "sauNumRegions", + "sauRegionsConfig", + }; - if (cpu.get_value("vtorPresent")) |vtor| - try db.add_device_property(device_id, "cpu.vtor", vtor); + for (required_properties) |property| { + const value = cpu.get_value(property) orelse { + std.log.err("missing cpu property: {s}", .{property}); + return error.MissingRequiredProperty; + }; - if (cpu.get_value("deviceNumInterrupts")) |num_interrupts| - try db.add_device_property(device_id, "cpu.num_interrupts", num_interrupts); + const property_name = try std.mem.join(db.arena.allocator(), ".", &.{ "cpu", property }); + try db.add_device_property(device_id, property_name, value); + } - // fpuDP - // sauNumRegions - // sauRegionsConfig + for (optional_properties) |property| { + if (cpu.get_value(property)) |value| { + const property_name = try std.mem.join(db.arena.allocator(), ".", &.{ "cpu", property }); + try db.add_device_property(device_id, property_name, value); + } + } } if (cpu_it.next() != null) log.warn("there are multiple CPUs", .{}); - if (db.instances.devices.getEntry(device_id)) |device| { - const arch = device.value_ptr.arch; - if (arch.is_arm()) try cmsis.add_core_registers(db, arch, device_id); - } - var ctx = Context{ .db = db, }; @@ -175,10 +153,13 @@ pub fn load_into_db(db: *Database, doc: xml.Doc) !void { }; } - if (db.instances.devices.getEntry(device_id)) |device| { - const arch = device.value_ptr.arch; - if (arch.is_arm()) try cmsis.add_nvic_fields(db, arch, device_id); - } + const device = db.instances.devices.getEntry(device_id).?.value_ptr; + device.arch = if (device.properties.get("cpu.name")) |cpu_name| + arch_from_str(cpu_name) + else + .unknown; + if (device.arch.is_arm()) + try arm.load_system_interrupts(db, device_id); db.assert_valid(); } diff --git a/tools/regz/src/svd/cmsis.zig b/tools/regz/src/svd/cmsis.zig deleted file mode 100644 index ebd1cd9..0000000 --- a/tools/regz/src/svd/cmsis.zig +++ /dev/null @@ -1,99 +0,0 @@ -const std = @import("std"); -const svd = @import("../svd.zig"); -const Database = @import("../Database.zig"); -const EntityId = Database.EntityId; - -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 add_systick_registers(db: *Database, device_id: EntityId, scs_id: EntityId) !void { - const systick_type = try db.create_register_group(scs_id, .{ - .name = "SysTick", - .description = "System Tick Timer", - }); - _ = try db.create_peripheral_instance(device_id, systick_type, .{ - .name = "SysTick", - .offset = 0xe000e010, - }); - - const ctrl_id = try db.create_register(systick_type, .{ - .name = "CTRL", - .description = "SysTick Control and Status Register", - .offset = 0x0, - .size = 32, - }); - const load_id = try db.create_register(systick_type, .{ - .name = "LOAD", - .description = "SysTick Reload Value Register", - .offset = 0x4, - .size = 32, - }); - const val_id = try db.create_register(systick_type, .{ - .name = "VAL", - .description = "SysTick Current Value Register", - .offset = 0x8, - .size = 32, - }); - const calib_id = try db.create_register(systick_type, .{ - .name = "CALIB", - .description = "SysTick Calibration Register", - .offset = 0xc, - .size = 32, - .access = .read_only, - }); - - // CTRL fields - _ = try db.create_field(ctrl_id, .{ .name = "ENABLE", .offset = 0, .size = 1 }); - _ = try db.create_field(ctrl_id, .{ .name = "TICKINT", .offset = 1, .size = 1 }); - _ = try db.create_field(ctrl_id, .{ .name = "CLKSOURCE", .offset = 2, .size = 1 }); - _ = try db.create_field(ctrl_id, .{ .name = "COUNTFLAG", .offset = 16, .size = 1 }); - - // LOAD fields - _ = try db.create_field(load_id, .{ .name = "RELOAD", .offset = 0, .size = 24 }); - - // VAL fields - _ = try db.create_field(val_id, .{ .name = "CURRENT", .offset = 0, .size = 24 }); - - // CALIB fields - _ = try db.create_field(calib_id, .{ .name = "TENMS", .offset = 0, .size = 24 }); - _ = try db.create_field(calib_id, .{ .name = "SKEW", .offset = 30, .size = 1 }); - _ = try db.create_field(calib_id, .{ .name = "NOREF", .offset = 31, .size = 1 }); -} - -pub fn add_core_registers(db: *Database, cpu_name: Database.Arch, device_id: EntityId) !void { - const type_id = try db.create_peripheral(.{ - .name = "SCS", - .description = "System Control Space", - }); - - if (db.instances.devices.get(device_id)) |cpu| { - if (!(try has_vendor_systick_config(cpu))) - try add_systick_registers(db, device_id, type_id); - - inline for (@typeInfo(cores).Struct.decls) |decl| - if (cpu_name == @field(Database.Arch, decl.name)) - try @field(cores, decl.name).add_core_registers(db, device_id, type_id); - } -} - -pub fn add_nvic_fields(db: *Database, cpu_name: Database.Arch, device_id: EntityId) !void { - inline for (@typeInfo(cores).Struct.decls) |decl| - if (cpu_name == @field(Database.Arch, decl.name)) - try @field(cores, decl.name).add_nvic_fields(db, device_id); -} - -fn has_vendor_systick_config(cpu: anytype) !bool { - if (cpu.properties.get("cpu.vendor_systick_config")) |systick| { - if (std.mem.eql(u8, systick, "false") or std.mem.eql(u8, systick, "0")) { - return false; - } else if (std.mem.eql(u8, systick, "true") or std.mem.eql(u8, systick, "1")) { - return true; - } else { - return error.BadVendorSystickConfigRepresentation; - } - } - return error.MissingVendorSystickConfig; -} diff --git a/tools/regz/src/svd/cmsis/cortex_m0.zig b/tools/regz/src/svd/cmsis/cortex_m0.zig deleted file mode 100644 index 99f518c..0000000 --- a/tools/regz/src/svd/cmsis/cortex_m0.zig +++ /dev/null @@ -1,199 +0,0 @@ -const std = @import("std"); -const Database = @import("../../Database.zig"); -const EntityId = Database.EntityId; - -const parseInt = std.fmt.parseInt; - -pub fn add_core_registers(db: *Database, device_id: EntityId, scs_id: EntityId) !void { - try add_nvic_cluster(db, device_id, scs_id); - try add_scb_cluster(db, device_id, scs_id); -} - -pub fn add_nvic_cluster(db: *Database, device_id: EntityId, scs_id: EntityId) !void { - const nvic = try db.create_register_group(scs_id, .{ - .name = "NVIC", - .description = "Nested Vectored Interrupt Controller", - }); - _ = try db.create_peripheral_instance(device_id, scs_id, .{ - .name = "NVIC", - .offset = 0xe000e100, - }); - - _ = try db.create_register(nvic, .{ - .name = "ISER", - .description = "Interrupt Set Enable Register", - .offset = 0x000, - .size = 32, - }); - _ = try db.create_register(nvic, .{ - .name = "ICER", - .description = "Interrupt Clear Enable Register", - .offset = 0x080, - .size = 32, - }); - _ = try db.create_register(nvic, .{ - .name = "ISPR", - .description = "Interrupt Set Pending Register", - .offset = 0x100, - .size = 32, - }); - _ = try db.create_register(nvic, .{ - .name = "ICPR", - .description = "Interrupt Clear Pending Register", - .offset = 0x180, - .size = 32, - }); - - // interrupt priority registers - if (db.instances.devices.get(device_id)) |cpu| - if (cpu.properties.get("cpu.nvic_prio_bits")) |bits| if (try parseInt(u32, bits, 10) > 0) { - const ip_addr_offset = 0x300; - - var i: u32 = 0; - while (i < 8) : (i += 1) { - const addr_offset = ip_addr_offset + (i * 4); - const reg_name = try std.fmt.allocPrint(db.arena.allocator(), "IPR{}", .{i}); - - _ = try db.create_register(nvic, .{ - .name = reg_name, - .description = "Interrupt Priority Register", - .offset = addr_offset, - .size = 32, - }); - } - }; -} - -pub fn add_nvic_fields(db: *Database, device_id: EntityId) !void { - const interrupt_registers: [4]EntityId = .{ - try db.get_entity_id_by_name("type.register", "ISER"), - try db.get_entity_id_by_name("type.register", "ICER"), - try db.get_entity_id_by_name("type.register", "ISPR"), - try db.get_entity_id_by_name("type.register", "ICPR"), - }; - - var interrupt_iter = db.instances.interrupts.iterator(); - while (interrupt_iter.next()) |interrupt_kv| { - if (interrupt_kv.value_ptr.* < 0) continue; - - const interrupt_name = db.attrs.name.get(interrupt_kv.key_ptr.*).?; - const interrupt_index = @bitCast(u32, interrupt_kv.value_ptr.*); - for (interrupt_registers) |register| { - _ = try db.create_field(register, .{ - .name = interrupt_name, - .offset = interrupt_index, - .size = 1, - }); - } - - const nvic_prio_bits = try parseInt( - u32, - db.instances.devices.get(device_id).?.properties.get("cpu.nvic_prio_bits") orelse return error.MissingNvicPrioBits, - 10, - ); - if (nvic_prio_bits == 0) continue; - - const reg_name = try std.fmt.allocPrint(db.arena.allocator(), "IPR{}", .{interrupt_index >> 2}); - const reg_id = try db.get_entity_id_by_name("type.register", reg_name); - - _ = try db.create_field(reg_id, .{ - .name = interrupt_name, - .offset = (8 * (@intCast(u8, interrupt_index) % 4)) + (8 - nvic_prio_bits), - .size = nvic_prio_bits, - }); - } -} - -pub fn add_scb_cluster(db: *Database, device_id: EntityId, scs_id: EntityId) !void { - const scb = try db.create_register_group(scs_id, .{ - .name = "SCB", - .description = "System Control Block", - }); - _ = try db.create_peripheral_instance(device_id, scs_id, .{ - .name = "SCB", - .offset = 0xe000ed00, - }); - - const cpuid = try db.create_register(scb, .{ - .name = "CPUID", - .offset = 0x000, - .access = .read_only, - .size = 32, - }); - const icsr = try db.create_register(scb, .{ - .name = "ICSR", - .description = "Interrupt Control and State Register", - .offset = 0x004, - .size = 32, - }); - const aircr = try db.create_register(scb, .{ - .name = "AIRCR", - .description = "Application Interrupt and Reset Control Register", - .offset = 0x00c, - .size = 32, - }); - const scr = try db.create_register(scb, .{ - .name = "SCR", - .description = "System Control Register", - .offset = 0x010, - .size = 32, - }); - const ccr = try db.create_register(scb, .{ - .name = "CCR", - .description = "Configuration Control Register", - .offset = 0x014, - .size = 32, - }); - const shp = try db.create_register(scb, .{ - .name = "SHP", - .description = "System Handlers Priority Registers. [0] is RESERVED", - .offset = 0x01c, - .size = 32, - //.dimension = .{ - // .dim = 2, - //}, - }); - _ = shp; - const shcsr = try db.create_register(scb, .{ - .name = "SHCSR", - .description = "System Handler Control and State Register", - .offset = 0x024, - .size = 32, - }); - - // CPUID fields - _ = try db.create_field(cpuid, .{ .name = "REVISION", .offset = 0, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "PARTNO", .offset = 4, .size = 12 }); - _ = try db.create_field(cpuid, .{ .name = "ARCHITECTURE", .offset = 16, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "VARIANT", .offset = 20, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "IMPLEMENTER", .offset = 24, .size = 8 }); - - // ICSR fields - _ = try db.create_field(icsr, .{ .name = "VECTACTIVE", .offset = 0, .size = 9 }); - _ = try db.create_field(icsr, .{ .name = "VECTPENDING", .offset = 12, .size = 9 }); - _ = try db.create_field(icsr, .{ .name = "ISRPENDING", .offset = 22, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "ISRPREEMPT", .offset = 23, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSTCLR", .offset = 25, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSTSET", .offset = 26, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSVCLR", .offset = 27, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSVSET", .offset = 28, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "NMIPENDSET", .offset = 31, .size = 1 }); - - // AIRCR fields - _ = try db.create_field(aircr, .{ .name = "VECTCLRACTIVE", .offset = 1, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "SYSRESETREQ", .offset = 2, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "ENDIANESS", .offset = 15, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "VECTKEY", .offset = 16, .size = 16 }); - - // SCR fields - _ = try db.create_field(scr, .{ .name = "SLEEPONEXIT", .offset = 1, .size = 1 }); - _ = try db.create_field(scr, .{ .name = "SLEEPDEEP", .offset = 2, .size = 1 }); - _ = try db.create_field(scr, .{ .name = "SEVONPEND", .offset = 4, .size = 1 }); - - // CCR fields - _ = try db.create_field(ccr, .{ .name = "UNALIGN_TRP", .offset = 3, .size = 1 }); - _ = try db.create_field(ccr, .{ .name = "STKALIGN", .offset = 9, .size = 1 }); - - // SHCSR fields - _ = try db.create_field(shcsr, .{ .name = "SVCALLPENDED", .offset = 15, .size = 1 }); -} diff --git a/tools/regz/src/svd/cmsis/cortex_m0plus.zig b/tools/regz/src/svd/cmsis/cortex_m0plus.zig deleted file mode 100644 index dccbc04..0000000 --- a/tools/regz/src/svd/cmsis/cortex_m0plus.zig +++ /dev/null @@ -1,187 +0,0 @@ -const std = @import("std"); -const Database = @import("../../Database.zig"); -const EntityId = Database.EntityId; -const cortex_m0 = @import("cortex_m0.zig"); - -pub const add_nvic_fields = cortex_m0.add_nvic_fields; - -pub fn add_core_registers(db: *Database, device_id: EntityId, scs: EntityId) !void { - const scb = try db.create_register_group(scs, .{ - .name = "SCB", - .description = "System Control Block", - }); - _ = try db.create_peripheral_instance(device_id, scs, .{ - .name = "SCB", - .offset = 0xe000ed00, - }); - - const cpuid = try db.create_register(scb, .{ - .name = "CPUID", - .offset = 0x000, - .access = .read_only, - .size = 32, - }); - const icsr = try db.create_register(scb, .{ - .name = "ICSR", - .description = "Interrupt Control and State Register", - .offset = 0x004, - .size = 32, - }); - const aircr = try db.create_register(scb, .{ - .name = "AIRCR", - .description = "Application Interrupt and Reset Control Register", - .offset = 0x00c, - .size = 32, - }); - const scr = try db.create_register(scb, .{ - .name = "SCR", - .description = "System Control Register", - .offset = 0x010, - .size = 32, - }); - const ccr = try db.create_register(scb, .{ - .name = "CCR", - .description = "Configuration Control Register", - .offset = 0x014, - .size = 32, - }); - const shp = try db.create_register(scb, .{ - .name = "SHP", - .description = "System Handlers Priority Registers. [0] is RESERVED", - .offset = 0x01c, - .size = 32, - //.dimension = .{ - // .dim = 2, - //}, - }); - _ = shp; - const shcsr = try db.create_register(scb, .{ - .name = "SHCSR", - .description = "System Handler Control and State Register", - .offset = 0x024, - .size = 32, - }); - - if (db.instances.devices.get(device_id)) |cpu| if (cpu.properties.get("cpu.vtor") != null) { - const vtor = try db.create_register(scb, .{ - .name = "VTOR", - .description = "Vector Table Offset Register", - .offset = 0x08, - .size = 32, - }); - - _ = try db.create_field(vtor, .{ - .name = "TBLOFF", - .offset = 8, - .size = 24, - }); - }; - - // CPUID fields - _ = try db.create_field(cpuid, .{ .name = "REVISION", .offset = 0, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "PARTNO", .offset = 4, .size = 12 }); - _ = try db.create_field(cpuid, .{ .name = "ARCHITECTURE", .offset = 16, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "VARIANT", .offset = 20, .size = 4 }); - _ = try db.create_field(cpuid, .{ .name = "IMPLEMENTER", .offset = 24, .size = 8 }); - - // ICSR fields - _ = try db.create_field(icsr, .{ .name = "VECTACTIVE", .offset = 0, .size = 9 }); - _ = try db.create_field(icsr, .{ .name = "VECTPENDING", .offset = 12, .size = 9 }); - _ = try db.create_field(icsr, .{ .name = "ISRPENDING", .offset = 22, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "ISRPREEMPT", .offset = 23, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSTCLR", .offset = 25, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSTSET", .offset = 26, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSVCLR", .offset = 27, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "PENDSVSET", .offset = 28, .size = 1 }); - _ = try db.create_field(icsr, .{ .name = "NMIPENDSET", .offset = 31, .size = 1 }); - - // AIRCR fields - _ = try db.create_field(aircr, .{ .name = "VECTCLRACTIVE", .offset = 1, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "SYSRESETREQ", .offset = 2, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "ENDIANESS", .offset = 15, .size = 1 }); - _ = try db.create_field(aircr, .{ .name = "VECTKEY", .offset = 16, .size = 16 }); - - // SCR fields - _ = try db.create_field(scr, .{ .name = "SLEEPONEXIT", .offset = 1, .size = 1 }); - _ = try db.create_field(scr, .{ .name = "SLEEPDEEP", .offset = 2, .size = 1 }); - _ = try db.create_field(scr, .{ .name = "SEVONPEND", .offset = 4, .size = 1 }); - - // CCR fields - _ = try db.create_field(ccr, .{ .name = "UNALIGN_TRP", .offset = 3, .size = 1 }); - _ = try db.create_field(ccr, .{ .name = "STKALIGN", .offset = 9, .size = 1 }); - - // SHCSR fields - _ = try db.create_field(shcsr, .{ .name = "SVCALLPENDED", .offset = 15, .size = 1 }); - - try cortex_m0.add_nvic_cluster(db, device_id, scs); - - if (db.instances.devices.get(device_id)) |cpu| if (cpu.properties.get("cpu.mpu") != null) - try add_mpu_registers(db, device_id, scs); -} - -fn add_mpu_registers(db: *Database, device_id: EntityId, scs: EntityId) !void { - const mpu = try db.create_register_group(scs, .{ - .name = "MPU", - .description = "Memory Protection Unit", - }); - _ = try db.create_peripheral_instance(device_id, scs, .{ - .name = "MPU", - .offset = 0xd90, - }); - - const type_reg = try db.create_register(mpu, .{ - .name = "TYPE", - .description = "MPU Type Register", - .offset = 0x00, - .access = .read_only, - .size = 32, - }); - const ctrl = try db.create_register(mpu, .{ - .name = "CTRL", - .description = "MPU Control Register", - .offset = 0x04, - .size = 32, - }); - const rnr = try db.create_register(mpu, .{ - .name = "RNR", - .description = "MPU Region RNRber Register", - .offset = 0x08, - .size = 32, - }); - const rbar = try db.create_register(mpu, .{ - .name = "RBAR", - .description = "MPU Region Base Address Register", - .offset = 0x0c, - .size = 32, - }); - const rasr = try db.create_register(mpu, .{ - .name = "RASR", - .description = "MPU Region Attribute and Size Register", - .offset = 0x10, - .size = 32, - }); - - _ = try db.create_field(type_reg, .{ .name = "SEPARATE", .offset = 0, .size = 1 }); - _ = try db.create_field(type_reg, .{ .name = "DREGION", .offset = 8, .size = 8 }); - _ = try db.create_field(type_reg, .{ .name = "IREGION", .offset = 16, .size = 8 }); - - _ = try db.create_field(ctrl, .{ .name = "ENABLE", .offset = 0, .size = 1 }); - _ = try db.create_field(ctrl, .{ .name = "HFNMIENA", .offset = 1, .size = 1 }); - _ = try db.create_field(ctrl, .{ .name = "PRIVDEFENA", .offset = 2, .size = 1 }); - - _ = try db.create_field(rnr, .{ .name = "REGION", .offset = 0, .size = 8 }); - - _ = try db.create_field(rbar, .{ .name = "REGION", .offset = 0, .size = 4 }); - _ = try db.create_field(rbar, .{ .name = "VALID", .offset = 4, .size = 1 }); - _ = try db.create_field(rbar, .{ .name = "ADDR", .offset = 8, .size = 24 }); - - _ = try db.create_field(rasr, .{ .name = "ENABLE", .offset = 0, .size = 1 }); - _ = try db.create_field(rasr, .{ .name = "SIZE", .offset = 1, .size = 5 }); - _ = try db.create_field(rasr, .{ .name = "SRD", .offset = 8, .size = 8 }); - _ = try db.create_field(rasr, .{ .name = "B", .offset = 16, .size = 1 }); - _ = try db.create_field(rasr, .{ .name = "C", .offset = 17, .size = 1 }); - _ = try db.create_field(rasr, .{ .name = "S", .offset = 18, .size = 1 }); - _ = try db.create_field(rasr, .{ .name = "TEX", .offset = 19, .size = 3 }); - _ = try db.create_field(rasr, .{ .name = "AP", .offset = 24, .size = 3 }); - _ = try db.create_field(rasr, .{ .name = "XN", .offset = 28, .size = 1 }); -} diff --git a/tools/regz/src/svd/cmsis/cortex_m1.zig b/tools/regz/src/svd/cmsis/cortex_m1.zig deleted file mode 100644 index 811417a..0000000 --- a/tools/regz/src/svd/cmsis/cortex_m1.zig +++ /dev/null @@ -1,30 +0,0 @@ -const std = @import("std"); -const Database = @import("../../Database.zig"); -const EntityId = Database.EntityId; -const cortex_m0 = @import("cortex_m0.zig"); - -pub const add_nvic_fields = cortex_m0.add_nvic_fields; - -pub fn add_core_registers(db: *Database, device_id: EntityId, scs_id: EntityId) !void { - try cortex_m0.add_nvic_cluster(db, device_id, scs_id); - try cortex_m0.add_scb_cluster(db, device_id, scs_id); - - const scnscb = try db.create_register_group(scs_id, .{ - .name = "SCnSCN", - .description = "System Control and ID Register not in the SCB", - }); - _ = try db.create_peripheral_instance(device_id, scnscb, .{ - .name = "SCnSCB", - .offset = 0x0, - }); - - const actlr = try db.create_register(scnscb, .{ - .name = "ACTLR", - .description = "Auxilary Control Register", - .offset = 0x8, - .size = 32, - }); - - _ = try db.create_field(actlr, .{ .name = "ITCMLAEN", .offset = 3, .size = 1 }); - _ = try db.create_field(actlr, .{ .name = "ITCMUAEN", .offset = 4, .size = 1 }); -}