diff --git a/port/raspberrypi/rp2xxx/src/hal/pio.zig b/port/raspberrypi/rp2xxx/src/hal/pio.zig index 76bf65b7..610bf0c5 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio.zig @@ -12,7 +12,7 @@ const chip_specific = switch (cpu) { .RP2350 => @import("pio/rp2350.zig"), }; pub const StateMachine = common.StateMachine; -pub const Instruction = common.Instruction; +pub const Instruction = common.Instruction(cpu); pub const PinMapping = common.PinMapping; pub const PinMappingOptions = common.PinMappingOptions; pub const StateMachineInitOptions = chip_specific.StateMachineInitOptions; @@ -24,7 +24,9 @@ pub const assembler = @import("pio/assembler.zig"); const encoder = @import("pio/assembler/encoder.zig"); pub const Program = assembler.Program; -pub const assemble = assembler.assemble; +pub inline fn assemble(comptime source: []const u8, comptime options: assembler.AssembleOptions) assembler.Output { + return assembler.assemble(cpu, source, options); +} pub fn num(n: u2) Pio { switch (cpu) { diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig index 949155cf..0de9635b 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler.zig @@ -2,7 +2,6 @@ const std = @import("std"); const assert = std.debug.assert; const CPU = @import("../cpu.zig").CPU; -// TODO: Isn't this circular? const tokenizer = @import("assembler/tokenizer.zig"); const encoder = @import("assembler/encoder.zig"); @@ -73,9 +72,9 @@ pub const Diagnostics = struct { } }; -pub fn assemble_impl(comptime format: Format, comptime source: []const u8, diags: *?Diagnostics, options: AssembleOptions) !Output { - const tokens = try tokenizer.tokenize(format, source, diags, options.tokenize); - const encoder_output = try encoder.encode(format, tokens.slice(), diags, options.encode); +pub fn assemble_impl(comptime cpu: CPU, comptime source: []const u8, diags: *?Diagnostics, options: AssembleOptions) !Output { + const tokens = try tokenizer.tokenize(cpu, source, diags, options.tokenize); + const encoder_output = try encoder.encode(cpu, tokens.slice(), diags, options.encode); var programs = std.BoundedArray(Program, options.encode.max_programs).init(0) catch unreachable; for (encoder_output.programs.slice()) |bounded| try programs.append(bounded.to_exported_program()); @@ -123,25 +122,9 @@ fn format_compile_error(comptime message: []const u8, comptime source: []const u }); } -// TODO: Place. Who should own this? -pub const Format = enum { - RP2040, - RP2350, -}; - -pub fn cpuToFormat(cpu: CPU) Format { - return switch (cpu) { - .RP2040 => .RP2040, - .RP2350 => .RP2350, - }; -} - -pub fn assemble(comptime source: []const u8, comptime options: AssembleOptions) Output { +pub fn assemble(comptime cpu: CPU, comptime source: []const u8, comptime options: AssembleOptions) Output { var diags: ?Diagnostics = null; - // TODO: We can't import compatibility & zig build test since it depends on microzig - // cpuToFormat(cpu) instead of hardcoding - // const cpu = @import("../compatibility.zig").cpu; - return assemble_impl(.RP2040, source, &diags, options) catch |err| if (diags) |d| + return assemble_impl(cpu, source, &diags, options) catch |err| if (diags) |d| @compileError(format_compile_error(d.message.slice(), source, d.index)) else @compileError(err); diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig index 5928a2a5..8f5ceac8 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig @@ -5,14 +5,11 @@ const assembler = @import("../assembler.zig"); const Diagnostics = assembler.Diagnostics; const tokenizer = @import("tokenizer.zig"); -// TODO: How do I pass in the format to this module? There is no (comptime) -// instance object -// const format: assembler.Format = .RP2350; -// const Token = tokenizer.Token(format); const Token = tokenizer.Token; const Value = tokenizer.Value; const Expression = @import("Expression.zig"); +const CPU = @import("../../cpu.zig").CPU; pub const Options = struct { max_defines: u32 = 16, @@ -20,13 +17,12 @@ pub const Options = struct { }; pub fn encode( - // We don't want the user to have to specify this - comptime format: assembler.Format, - comptime tokens: []const Token(format), + comptime cpu: CPU, + comptime tokens: []const Token(cpu), diags: *?assembler.Diagnostics, comptime options: Options, -) !Encoder(format, options).Output { - var encoder = Encoder(format, options).init(tokens); +) !Encoder(cpu, options).Output { + var encoder = Encoder(cpu, options).init(tokens); return try encoder.encode_output(diags); } @@ -47,10 +43,10 @@ pub const DefineWithIndex = struct { index: u32, }; -pub fn Encoder(comptime format: assembler.Format, comptime options: Options) type { +pub fn Encoder(comptime cpu: CPU, comptime options: Options) type { return struct { output: Self.Output, - tokens: []const Token(format), + tokens: []const Token(cpu), index: u32, const Self = @This(); @@ -62,7 +58,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ const BoundedDefines = std.BoundedArray(DefineWithIndex, options.max_defines); const BoundedPrograms = std.BoundedArray(BoundedProgram, options.max_programs); - const BoundedInstructions = std.BoundedArray(Instruction(format), 32); + const BoundedInstructions = std.BoundedArray(Instruction(cpu), 32); const BoundedLabels = std.BoundedArray(Label, 32); const Label = struct { name: []const u8, @@ -111,7 +107,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ } }; - fn init(tokens: []const Token(format)) Self { + fn init(tokens: []const Token(cpu)) Self { return Self{ .output = Self.Output{ .global_defines = BoundedDefines.init(0) catch unreachable, @@ -123,14 +119,14 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ }; } - fn peek_token(self: Self) ?Token(format) { + fn peek_token(self: Self) ?Token(cpu) { return if (self.index < self.tokens.len) self.tokens[self.index] else null; } - fn get_token(self: *Self) ?Token(format) { + fn get_token(self: *Self) ?Token(cpu) { return if (self.peek_token()) |token| blk: { self.consume(1); break :blk token; @@ -309,12 +305,12 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ fn encode_instruction( self: *Self, program: *BoundedProgram, - token: Token(format).Instruction, + token: Token(cpu).Instruction, token_index: u32, diags: *?Diagnostics, ) !void { // guaranteed to be an instruction variant - const payload: Instruction(format).Payload = switch (token.payload) { + const payload: Instruction(cpu).Payload = switch (token.payload) { .nop => .{ .mov = .{ .destination = .y, @@ -368,7 +364,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ }, }, .irq => |irq| blk: { - switch (format) { + switch (cpu) { .RP2040 => { const irq_num = try self.evaluate(u5, program.*, irq.num, token_index, diags); break :blk .{ @@ -403,7 +399,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ }, }; - const tag: Instruction(format).Tag = switch (token.payload) { + const tag: Instruction(cpu).Tag = switch (token.payload) { .nop => .mov, .jmp => .jmp, .wait => .wait, @@ -444,7 +440,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ delay, ); - try program.instructions.append(Instruction(format){ + try program.instructions.append(Instruction(cpu){ .tag = tag, .payload = payload, .delay_side_set = delay_side_set, @@ -507,7 +503,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ switch (token.data) { .instruction => |instr| try self.encode_instruction(program, instr, token.index, diags), .word => |word| try program.instructions.append( - @as(Instruction(format), @bitCast(try self.evaluate(u16, program.*, word, token.index, diags))), + @as(Instruction(cpu), @bitCast(try self.evaluate(u16, program.*, word, token.index, diags))), ), // already processed .label, .wrap_target, .wrap => {}, @@ -556,7 +552,7 @@ pub fn Encoder(comptime format: assembler.Format, comptime options: Options) typ }; } -pub fn Instruction(comptime format: assembler.Format) type { +pub fn Instruction(comptime cpu: CPU) type { return packed struct(u16) { payload: Payload, delay_side_set: u5, @@ -587,23 +583,23 @@ pub fn Instruction(comptime format: assembler.Format) type { pub const Jmp = packed struct(u8) { address: u5, - condition: Token(format).Instruction.Jmp.Condition, + condition: Token(cpu).Instruction.Jmp.Condition, }; pub const Wait = packed struct(u8) { index: u5, - source: Token(format).Instruction.Wait.Source, + source: Token(cpu).Instruction.Wait.Source, polarity: u1, }; pub const In = packed struct(u8) { bit_count: u5, - source: Token(format).Instruction.In.Source, + source: Token(cpu).Instruction.In.Source, }; pub const Out = packed struct(u8) { bit_count: u5, - destination: Token(format).Instruction.Out.Destination, + destination: Token(cpu).Instruction.Out.Destination, }; pub const Push = packed struct(u8) { @@ -621,12 +617,12 @@ pub fn Instruction(comptime format: assembler.Format) type { }; pub const Mov = packed struct(u8) { - source: Token(format).Instruction.Mov.Source, - operation: Token(format).Instruction.Mov.Operation, - destination: Token(format).Instruction.Mov.Destination, + source: Token(cpu).Instruction.Mov.Source, + operation: Token(cpu).Instruction.Mov.Operation, + destination: Token(cpu).Instruction.Mov.Destination, }; - pub const Irq = switch (format) { + pub const Irq = switch (cpu) { .RP2040 => packed struct(u8) { index: u5, wait: u1, @@ -644,7 +640,7 @@ pub fn Instruction(comptime format: assembler.Format) type { pub const Set = packed struct(u8) { data: u5, - destination: Token(format).Instruction.Set.Destination, + destination: Token(cpu).Instruction.Set.Destination, }; }; } @@ -657,15 +653,15 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectEqualStrings = std.testing.expectEqualStrings; -fn encode_bounded_output_impl(comptime format: assembler.Format, source: []const u8, diags: *?assembler.Diagnostics) !Encoder(format, .{}).Output { - const tokens = try tokenizer.tokenize(format, source, diags, .{}); - var encoder = Encoder(format, .{}).init(tokens.slice()); +fn encode_bounded_output_impl(comptime cpu: CPU, source: []const u8, diags: *?assembler.Diagnostics) !Encoder(cpu, .{}).Output { + const tokens = try tokenizer.tokenize(cpu, source, diags, .{}); + var encoder = Encoder(cpu, .{}).init(tokens.slice()); return try encoder.encode_output(diags); } -fn encode_bounded_output(comptime format: assembler.Format, source: []const u8) !Encoder(format, .{}).Output { +fn encode_bounded_output(comptime cpu: CPU, source: []const u8) !Encoder(cpu, .{}).Output { var diags: ?assembler.Diagnostics = null; - return encode_bounded_output_impl(format, source, &diags) catch |err| if (diags) |d| blk: { + return encode_bounded_output_impl(cpu, source, &diags) catch |err| if (diags) |d| blk: { std.log.err("error at index {}: {s}", .{ d.index, d.message.slice() }); break :blk err; } else err; diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig index ca53542b..9839aa98 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig @@ -5,19 +5,20 @@ const assembler = @import("../assembler.zig"); const Diagnostics = assembler.Diagnostics; const Expression = @import("Expression.zig"); +const CPU = @import("../../cpu.zig").CPU; pub const Options = struct { capacity: u32 = 256, }; pub fn tokenize( - comptime format: assembler.Format, + comptime cpu: CPU, source: []const u8, diags: *?assembler.Diagnostics, comptime options: Options, -) !std.BoundedArray(Token(format), options.capacity) { - var tokens = std.BoundedArray(Token(format), options.capacity).init(0) catch unreachable; - var tokenizer = Tokenizer(format).init(source); +) !std.BoundedArray(Token(cpu), options.capacity) { + var tokens = std.BoundedArray(Token(cpu), options.capacity).init(0) catch unreachable; + var tokenizer = Tokenizer(cpu).init(source); while (try tokenizer.next(diags)) |token| try tokens.append(token); @@ -63,15 +64,13 @@ pub const Value = union(enum) { // '/' -> '*' -> block comment // '%' -> -> -> -> '{' -> code block // '.' -> directive -pub fn Tokenizer(format: assembler.Format) type { +pub fn Tokenizer(cpu: CPU) type { return struct { const Self = @This(); - format: assembler.Format, source: []const u8, index: u32, - // TODO: Avoid name collision with the format field - pub fn format2( + pub fn format( self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, @@ -101,7 +100,6 @@ pub fn Tokenizer(format: assembler.Format) type { fn init(source: []const u8) Self { return Self{ - .format = format, .source = source, .index = 0, }; @@ -312,12 +310,12 @@ pub fn Tokenizer(format: assembler.Format) type { TooBig, }; - fn get_program(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_program(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { const name = (try self.get_arg(diags)) orelse { diags.* = Diagnostics.init(index, "missing program name", .{}); return error.MissingArg; }; - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .program = name }, }; @@ -340,7 +338,7 @@ pub fn Tokenizer(format: assembler.Format) type { return std.mem.eql(u8, &buf, lhs); } - fn get_define(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_define(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { const maybe_public = try self.get_identifier(); const is_public = eql_lower("public", maybe_public.str); @@ -349,7 +347,7 @@ pub fn Tokenizer(format: assembler.Format) type { else maybe_public; - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .define = .{ @@ -408,9 +406,9 @@ pub fn Tokenizer(format: assembler.Format) type { return error.NoValue; } - fn get_origin(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_origin(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { _ = diags; - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .origin = try self.get_value(), @@ -418,7 +416,7 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_side_set(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_side_set(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { const args = try self.get_args(3, diags); const count = try Value.from_string(args[0] orelse { diags.* = Diagnostics.init(index, "missing count", .{}); @@ -439,7 +437,7 @@ pub fn Tokenizer(format: assembler.Format) type { pindirs = true; } - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .side_set = .{ @@ -451,23 +449,23 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_wrap_target(_: *Self, index: u32, _: *?Diagnostics) TokenizeError!Token(format) { - return Token(format){ + fn get_wrap_target(_: *Self, index: u32, _: *?Diagnostics) TokenizeError!Token(cpu) { + return Token(cpu){ .index = index, .data = .{ .wrap_target = {} }, }; } - fn get_wrap(_: *Self, index: u32, _: *?Diagnostics) TokenizeError!Token(format) { - return Token(format){ + fn get_wrap(_: *Self, index: u32, _: *?Diagnostics) TokenizeError!Token(cpu) { + return Token(cpu){ .index = index, .data = .{ .wrap = {} }, }; } - fn get_lang_opt(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_lang_opt(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { _ = diags; - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .lang_opt = .{ @@ -479,15 +477,15 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_word(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(format) { + fn get_word(self: *Self, index: u32, diags: *?Diagnostics) TokenizeError!Token(cpu) { _ = diags; - return Token(format){ + return Token(cpu){ .index = index, .data = .{ .word = try self.get_value() }, }; } - const directives = std.StaticStringMap(*const fn (*Self, u32, *?Diagnostics) TokenizeError!Token(format)).initComptime(.{ + const directives = std.StaticStringMap(*const fn (*Self, u32, *?Diagnostics) TokenizeError!Token(cpu)).initComptime(.{ .{ "program", get_program }, .{ "define", get_define }, .{ "origin", get_origin }, @@ -498,7 +496,7 @@ pub fn Tokenizer(format: assembler.Format) type { .{ "word", get_word }, }); - fn get_directive(self: *Self, diags: *?Diagnostics) !Token(format) { + fn get_directive(self: *Self, diags: *?Diagnostics) !Token(cpu) { const index = self.index; const identifier = try self.read_until_whitespace_or_end(); return if (directives.get(identifier)) |handler| ret: { @@ -508,22 +506,22 @@ pub fn Tokenizer(format: assembler.Format) type { } else error.InvalidDirective; } - fn get_nop(_: *Self, _: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { - return Token(format).Instruction.Payload{ + fn get_nop(_: *Self, _: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { + return Token(cpu).Instruction.Payload{ .nop = {}, }; } - fn target_from_string(str: []const u8) TokenizeError!Token(format).Instruction.Jmp.Target { + fn target_from_string(str: []const u8) TokenizeError!Token(cpu).Instruction.Jmp.Target { const value = Value.from_string(str); - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .jmp = .{ .condition = .always, .target = switch (value) { - .string => |label| Token(format).Instruction.Jmp.Target{ + .string => |label| Token(cpu).Instruction.Jmp.Target{ .label = label, }, - else => Token(format).Instruction.Jmp.Target{ + else => Token(cpu).Instruction.Jmp.Target{ .value = value, }, }, @@ -531,8 +529,8 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_jmp(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { - const Condition = Token(format).Instruction.Jmp.Condition; + fn get_jmp(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { + const Condition = Token(cpu).Instruction.Jmp.Condition; const conditions = std.StaticStringMap(Condition).initComptime(.{ .{ "!x", .x_is_zero }, .{ "x--", .x_dec }, @@ -551,12 +549,12 @@ pub fn Tokenizer(format: assembler.Format) type { else (try self.get_arg(diags)) orelse return error.MissingArg; - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .jmp = .{ .condition = cond, .target = target_str }, }; } - fn get_wait(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_wait(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const polarity = try std.fmt.parseInt(u1, (try self.get_arg(diags)) orelse return error.MissingArg, 0); const source_str = (try self.get_arg(diags)) orelse return error.MissingArg; const pin = try Value.from_string((try self.get_arg(diags)) orelse return error.MissingArg); @@ -566,7 +564,7 @@ pub fn Tokenizer(format: assembler.Format) type { buf[i] = std.ascii.toLower(c); const source_lower = buf[0..source_str.len]; - const source: Token(format).Instruction.Wait.Source = + const source: Token(cpu).Instruction.Wait.Source = if (std.mem.eql(u8, "gpio", source_lower)) .gpio else if (std.mem.eql(u8, "pin", source_lower)) @@ -587,7 +585,7 @@ pub fn Tokenizer(format: assembler.Format) type { else false; - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .wait = .{ .polarity = polarity, .source = source, @@ -613,7 +611,7 @@ pub fn Tokenizer(format: assembler.Format) type { // I need to keep in mind with `get_args()` is that I must only consume the // args that are used. side set and delay may be on the same line - fn get_in(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_in(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const source_str = (try self.get_arg(diags)) orelse return error.MissingArg; const bit_count_str = (try self.get_arg(diags)) orelse return error.MissingArg; @@ -624,15 +622,15 @@ pub fn Tokenizer(format: assembler.Format) type { else @as(u5, @intCast(bit_count_tmp)); - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .in = .{ - .source = std.meta.stringToEnum(Token(format).Instruction.In.Source, source_lower.slice()) orelse return error.InvalidSource, + .source = std.meta.stringToEnum(Token(cpu).Instruction.In.Source, source_lower.slice()) orelse return error.InvalidSource, .bit_count = bit_count, }, }; } - fn get_out(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_out(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const dest_src = (try self.get_arg(diags)) orelse return error.MissingArg; const bit_count_str = (try self.get_arg(diags)) orelse return error.MissingArg; @@ -643,9 +641,9 @@ pub fn Tokenizer(format: assembler.Format) type { else @as(u5, @intCast(bit_count_tmp)); - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .out = .{ - .destination = std.meta.stringToEnum(Token(format).Instruction.Out.Destination, dest_lower.slice()) orelse return error.InvalidDestination, + .destination = std.meta.stringToEnum(Token(cpu).Instruction.Out.Destination, dest_lower.slice()) orelse return error.InvalidDestination, .bit_count = bit_count, }, }; @@ -667,7 +665,7 @@ pub fn Tokenizer(format: assembler.Format) type { true; } - fn get_push(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_push(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { return if (try self.peek_arg(diags)) |first_result| ret: { const lower = try lowercase_bounded(256, first_result.str); const iffull = std.mem.eql(u8, "iffull", lower.slice()); @@ -680,13 +678,13 @@ pub fn Tokenizer(format: assembler.Format) type { true; } else try self.block_from_peek(first_result); - break :ret Token(format).Instruction.Payload{ + break :ret Token(cpu).Instruction.Payload{ .push = .{ .iffull = iffull, .block = block, }, }; - } else Token(format).Instruction.Payload{ + } else Token(cpu).Instruction.Payload{ .push = .{ .iffull = false, .block = true, @@ -694,7 +692,7 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_pull(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_pull(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { return if (try self.peek_arg(diags)) |first_result| ret: { const lower = try lowercase_bounded(256, first_result.str); const ifempty = std.mem.eql(u8, "ifempty", lower.slice()); @@ -707,13 +705,13 @@ pub fn Tokenizer(format: assembler.Format) type { true; } else try self.block_from_peek(first_result); - break :ret Token(format).Instruction.Payload{ + break :ret Token(cpu).Instruction.Payload{ .pull = .{ .ifempty = ifempty, .block = block, }, }; - } else Token(format).Instruction.Payload{ + } else Token(cpu).Instruction.Payload{ .pull = .{ .ifempty = false, .block = true, @@ -721,10 +719,10 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_mov(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_mov(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const dest_str = (try self.get_arg(diags)) orelse return error.MissingArg; const dest_lower = try lowercase_bounded(256, dest_str); - const destination = std.meta.stringToEnum(Token(format).Instruction.Mov.Destination, dest_lower.slice()) orelse return error.InvalidDestination; + const destination = std.meta.stringToEnum(Token(cpu).Instruction.Mov.Destination, dest_lower.slice()) orelse return error.InvalidDestination; const second = try self.get_arg(diags) orelse return error.MissingArg; const op_prefixed: ?[]const u8 = if (std.mem.startsWith(u8, second, "!")) @@ -745,8 +743,8 @@ pub fn Tokenizer(format: assembler.Format) type { second; const source_lower = try lowercase_bounded(256, source_str); - const source = std.meta.stringToEnum(Token(format).Instruction.Mov.Source, source_lower.slice()) orelse return error.InvalidSource; - const operation: Token(format).Instruction.Mov.Operation = if (op_prefixed) |op_str| + const source = std.meta.stringToEnum(Token(cpu).Instruction.Mov.Source, source_lower.slice()) orelse return error.InvalidSource; + const operation: Token(cpu).Instruction.Mov.Operation = if (op_prefixed) |op_str| if (std.mem.eql(u8, "!", op_str)) .invert else if (std.mem.eql(u8, "~", op_str)) @@ -758,7 +756,7 @@ pub fn Tokenizer(format: assembler.Format) type { else .none; - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .mov = .{ .destination = destination, .source = source, @@ -767,7 +765,7 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn get_irq(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_irq(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const first = (try self.get_arg(diags)) orelse return error.MissingArg; var clear = false; @@ -798,7 +796,7 @@ pub fn Tokenizer(format: assembler.Format) type { first, }; - switch (comptime format) { + switch (comptime cpu) { .RP2040 => { const rel: bool = if (try self.peek_arg(diags)) |result| blk: { const rel_lower = try lowercase_bounded(256, result.str); @@ -809,7 +807,7 @@ pub fn Tokenizer(format: assembler.Format) type { break :blk is_rel; } else false; - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .irq = .{ .clear = clear, .wait = wait, @@ -847,7 +845,7 @@ pub fn Tokenizer(format: assembler.Format) type { } else 0b00; // } else .direct; - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .irq = .{ .clear = clear, .wait = wait, @@ -859,7 +857,7 @@ pub fn Tokenizer(format: assembler.Format) type { } } - fn get_set(self: *Self, diags: *?Diagnostics) TokenizeError!Token(format).Instruction.Payload { + fn get_set(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const dest_str = (try self.get_arg(diags)) orelse { diags.* = Diagnostics.init(0, "missing destination", .{}); return error.MissingArg; @@ -868,15 +866,15 @@ pub fn Tokenizer(format: assembler.Format) type { const dest_lower = try lowercase_bounded(256, dest_str); - return Token(format).Instruction.Payload{ + return Token(cpu).Instruction.Payload{ .set = .{ - .destination = std.meta.stringToEnum(Token(format).Instruction.Set.Destination, dest_lower.slice()) orelse return error.InvalidDestination, + .destination = std.meta.stringToEnum(Token(cpu).Instruction.Set.Destination, dest_lower.slice()) orelse return error.InvalidDestination, .value = value, }, }; } - const instructions = std.StaticStringMap(*const fn (*Self, *?Diagnostics) TokenizeError!Token(format).Instruction.Payload).initComptime(.{ + const instructions = std.StaticStringMap(*const fn (*Self, *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload).initComptime(.{ .{ "nop", get_nop }, .{ "jmp", get_jmp }, .{ "wait", get_wait }, @@ -889,7 +887,7 @@ pub fn Tokenizer(format: assembler.Format) type { .{ "set", get_set }, }); - fn get_instruction(self: *Self, name: Identifier, diags: *?Diagnostics) !Token(format) { + fn get_instruction(self: *Self, name: Identifier, diags: *?Diagnostics) !Token(cpu) { const name_lower = try lowercase_bounded(256, name.str); const payload = if (instructions.get(name_lower.slice())) |handler| try handler(self, diags) @@ -930,7 +928,7 @@ pub fn Tokenizer(format: assembler.Format) type { } self.skip_line(); - return Token(format){ + return Token(cpu){ .index = name.index, .data = .{ .instruction = .{ @@ -942,7 +940,7 @@ pub fn Tokenizer(format: assembler.Format) type { }; } - fn next(self: *Self, diags: *?assembler.Diagnostics) !?Token(format) { + fn next(self: *Self, diags: *?assembler.Diagnostics) !?Token(cpu) { while (self.peek()) |p| { switch (p) { ' ', '\t', '\n', '\r', ',' => self.consume(1), @@ -971,7 +969,7 @@ pub fn Tokenizer(format: assembler.Format) type { // definitely a label return if (eql_lower("public", first.str)) - Token(format){ + Token(cpu){ .index = first.index, .data = .{ .label = .{ @@ -984,7 +982,7 @@ pub fn Tokenizer(format: assembler.Format) type { }, } else if (std.mem.endsWith(u8, first.str, ":")) - Token(format){ + Token(cpu){ .index = first.index, .data = .{ .label = .{ @@ -1004,7 +1002,7 @@ pub fn Tokenizer(format: assembler.Format) type { }; } -pub fn Token(comptime format: assembler.Format) type { +pub fn Token(comptime cpu: CPU) type { return struct { const Self = @This(); index: u32, @@ -1021,7 +1019,7 @@ pub fn Token(comptime format: assembler.Format) type { instruction: Instruction, }, - pub const Tag = std.meta.Tag(std.meta.FieldType(Token(format), .data)); + pub const Tag = std.meta.Tag(std.meta.FieldType(Token(cpu), .data)); pub const Label = struct { name: []const u8, @@ -1071,7 +1069,7 @@ pub fn Token(comptime format: assembler.Format) type { num: Value, rel: bool, - pub const Source = switch (format) { + pub const Source = switch (cpu) { .RP2040 => enum(u2) { gpio = 0b00, pin = 0b01, @@ -1132,7 +1130,7 @@ pub fn Token(comptime format: assembler.Format) type { operation: Operation, source: Source, - pub const Destination = switch (format) { + pub const Destination = switch (cpu) { .RP2040 => enum(u3) { pins = 0b000, x = 0b001, @@ -1171,7 +1169,7 @@ pub fn Token(comptime format: assembler.Format) type { }; }; - pub const Irq = switch (format) { + pub const Irq = switch (cpu) { .RP2040 => struct { clear: bool, wait: bool, @@ -1235,15 +1233,15 @@ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectEqualStrings = std.testing.expectEqualStrings; -fn DirectiveTag(comptime format: assembler.Format) type { - return @typeInfo(Token(format).Directive).Union.tag_type.?; +fn DirectiveTag(comptime cpu: CPU) type { + return @typeInfo(Token(cpu).Directive).Union.tag_type.?; } -fn PayloadTag(comptime format: assembler.Format) type { - return @typeInfo(Token(format).Instruction.Payload).Union.tag_type.?; +fn PayloadTag(comptime cpu: CPU) type { + return @typeInfo(Token(cpu).Instruction.Payload).Union.tag_type.?; } -fn expect_program(comptime format: assembler.Format, expected: []const u8, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.program, @as(Token(format).Tag, actual.data)); +fn expect_program(comptime cpu: CPU, expected: []const u8, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.program, @as(Token(cpu).Tag, actual.data)); try expectEqualStrings(expected, actual.data.program); } @@ -1264,21 +1262,21 @@ fn expect_opt_value(expected: ?Value, actual: ?Value) !void { }; } -fn expect_define(comptime format: assembler.Format, expected: Token(format).Define, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.define, @as(Token(format).Tag, actual.data)); +fn expect_define(comptime cpu: CPU, expected: Token(cpu).Define, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.define, @as(Token(cpu).Tag, actual.data)); const define = actual.data.define; try expectEqualStrings(expected.name, define.name); try expect_value(expected.value, define.value); } -fn expect_origin(comptime format: assembler.Format, expected: Value, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.origin, @as(Token(format).Tag, actual.data)); +fn expect_origin(comptime cpu: CPU, expected: Value, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.origin, @as(Token(cpu).Tag, actual.data)); try expect_value(expected, actual.data.origin); } -fn expect_side_set(comptime format: assembler.Format, expected: Token(format).SideSet, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.side_set, @as(Token(format).Tag, actual.data)); +fn expect_side_set(comptime cpu: CPU, expected: Token(cpu).SideSet, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.side_set, @as(Token(cpu).Tag, actual.data)); const side_set = actual.data.side_set; try expect_value(expected.count, side_set.count); @@ -1286,16 +1284,16 @@ fn expect_side_set(comptime format: assembler.Format, expected: Token(format).Si try expectEqual(expected.pindir, side_set.pindir); } -fn expect_wrap_target(comptime format: assembler.Format, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.wrap_target, @as(Token(format).Tag, actual.data)); +fn expect_wrap_target(comptime cpu: CPU, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.wrap_target, @as(Token(cpu).Tag, actual.data)); } -fn expect_wrap(comptime format: assembler.Format, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.wrap, @as(Token(format).Tag, actual.data)); +fn expect_wrap(comptime cpu: CPU, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.wrap, @as(Token(cpu).Tag, actual.data)); } -fn expect_lang_opt(comptime format: assembler.Format, expected: Token(format).LangOpt, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.lang_opt, @as(Token(format).Tag, actual.data)); +fn expect_lang_opt(comptime cpu: CPU, expected: Token(cpu).LangOpt, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.lang_opt, @as(Token(cpu).Tag, actual.data)); const lang_opt = actual.data.lang_opt; try expectEqualStrings(expected.lang, lang_opt.lang); @@ -1303,13 +1301,13 @@ fn expect_lang_opt(comptime format: assembler.Format, expected: Token(format).La try expectEqualStrings(expected.option, lang_opt.option); } -fn expect_word(comptime format: assembler.Format, expected: Value, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.word, @as(Token(format).Tag, actual.data)); +fn expect_word(comptime cpu: CPU, expected: Value, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.word, @as(Token(cpu).Tag, actual.data)); try expect_value(expected, actual.data.word); } -fn expect_label(comptime format: assembler.Format, expected: Token(format).Label, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.label, @as(Token(format).Tag, actual.data)); +fn expect_label(comptime cpu: CPU, expected: Token(cpu).Label, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.label, @as(Token(cpu).Tag, actual.data)); const label = actual.data.label; try expectEqual(expected.public, label.public); @@ -1321,27 +1319,27 @@ const ExpectedNopInstr = struct { side_set: ?Value = null, }; -fn expect_instr_nop(comptime format: assembler.Format, expected: ExpectedNopInstr, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).nop, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_nop(comptime cpu: CPU, expected: ExpectedNopInstr, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).nop, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); try expect_opt_value(expected.side_set, instr.side_set); } -fn ExpectedSetInstr(comptime format: assembler.Format) type { +fn ExpectedSetInstr(comptime cpu: CPU) type { return struct { - dest: Token(format).Instruction.Set.Destination, + dest: Token(cpu).Instruction.Set.Destination, value: Value, delay: ?Value = null, side_set: ?Value = null, }; } -fn expect_instr_set(comptime format: assembler.Format, expected: ExpectedSetInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).set, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_set(comptime cpu: CPU, expected: ExpectedSetInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).set, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1352,18 +1350,18 @@ fn expect_instr_set(comptime format: assembler.Format, expected: ExpectedSetInst try expect_value(expected.value, set.value); } -fn ExpectedJmpInstr(comptime format: assembler.Format) type { +fn ExpectedJmpInstr(comptime cpu: CPU) type { return struct { - cond: Token(format).Instruction.Jmp.Condition = .always, + cond: Token(cpu).Instruction.Jmp.Condition = .always, target: []const u8, delay: ?Value = null, side_set: ?Value = null, }; } -fn expect_instr_jmp(comptime format: assembler.Format, expected: ExpectedJmpInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).jmp, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_jmp(comptime cpu: CPU, expected: ExpectedJmpInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).jmp, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1374,10 +1372,10 @@ fn expect_instr_jmp(comptime format: assembler.Format, expected: ExpectedJmpInst try expectEqualStrings(expected.target, jmp.target); } -fn ExpectedWaitInstr(comptime format: assembler.Format) type { +fn ExpectedWaitInstr(comptime cpu: CPU) type { return struct { polarity: u1, - source: Token(format).Instruction.Wait.Source, + source: Token(cpu).Instruction.Wait.Source, num: Value, // only valid for irq source rel: bool = false, @@ -1386,9 +1384,9 @@ fn ExpectedWaitInstr(comptime format: assembler.Format) type { }; } -fn expect_instr_wait(comptime format: assembler.Format, expected: ExpectedWaitInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).wait, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_wait(comptime cpu: CPU, expected: ExpectedWaitInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).wait, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1400,18 +1398,18 @@ fn expect_instr_wait(comptime format: assembler.Format, expected: ExpectedWaitIn try expect_value(expected.num, wait.num); } -fn ExpectedInInstr(comptime format: assembler.Format) type { +fn ExpectedInInstr(comptime cpu: CPU) type { return struct { - source: Token(format).Instruction.In.Source, + source: Token(cpu).Instruction.In.Source, bit_count: u5, delay: ?Value = null, side_set: ?Value = null, }; } -fn expect_instr_in(comptime format: assembler.Format, expected: ExpectedInInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).in, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_in(comptime cpu: CPU, expected: ExpectedInInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).in, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1422,18 +1420,18 @@ fn expect_instr_in(comptime format: assembler.Format, expected: ExpectedInInstr( try expectEqual(expected.bit_count, in.bit_count); } -fn ExpectedOutInstr(comptime format: assembler.Format) type { +fn ExpectedOutInstr(comptime cpu: CPU) type { return struct { - destination: Token(format).Instruction.Out.Destination, + destination: Token(cpu).Instruction.Out.Destination, bit_count: u5, delay: ?Value = null, side_set: ?Value = null, }; } -fn expect_instr_out(comptime format: assembler.Format, expected: ExpectedOutInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).out, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_out(comptime cpu: CPU, expected: ExpectedOutInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).out, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1451,9 +1449,9 @@ const ExpectedPushInstr = struct { side_set: ?Value = null, }; -fn expect_instr_push(comptime format: assembler.Format, expected: ExpectedPushInstr, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).push, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_push(comptime cpu: CPU, expected: ExpectedPushInstr, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).push, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1471,9 +1469,9 @@ const ExpectedPullInstr = struct { side_set: ?Value = null, }; -fn expect_instr_pull(comptime format: assembler.Format, expected: ExpectedPullInstr, actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).pull, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_pull(comptime cpu: CPU, expected: ExpectedPullInstr, actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).pull, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1484,19 +1482,19 @@ fn expect_instr_pull(comptime format: assembler.Format, expected: ExpectedPullIn try expectEqual(expected.ifempty, pull.ifempty); } -fn ExpectedMovInstr(comptime format: assembler.Format) type { +fn ExpectedMovInstr(comptime cpu: CPU) type { return struct { - source: Token(format).Instruction.Mov.Source, - destination: Token(format).Instruction.Mov.Destination, - operation: Token(format).Instruction.Mov.Operation = .none, + source: Token(cpu).Instruction.Mov.Source, + destination: Token(cpu).Instruction.Mov.Destination, + operation: Token(cpu).Instruction.Mov.Operation = .none, delay: ?Value = null, side_set: ?Value = null, }; } -fn expect_instr_mov(comptime format: assembler.Format, expected: ExpectedMovInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).mov, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_mov(comptime cpu: CPU, expected: ExpectedMovInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).mov, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1508,8 +1506,8 @@ fn expect_instr_mov(comptime format: assembler.Format, expected: ExpectedMovInst try expectEqual(expected.destination, mov.destination); } -fn ExpectedIrqInstr(comptime format: assembler.Format) type { - return switch (format) { +fn ExpectedIrqInstr(comptime cpu: CPU) type { + return switch (cpu) { .RP2040 => struct { clear: bool, wait: bool, @@ -1529,9 +1527,9 @@ fn ExpectedIrqInstr(comptime format: assembler.Format) type { }; } -fn expect_instr_irq(comptime format: assembler.Format, expected: ExpectedIrqInstr(format), actual: Token(format)) !void { - try expectEqual(Token(format).Tag.instruction, @as(Token(format).Tag, actual.data)); - try expectEqual(PayloadTag(format).irq, @as(PayloadTag(format), actual.data.instruction.payload)); +fn expect_instr_irq(comptime cpu: CPU, expected: ExpectedIrqInstr(cpu), actual: Token(cpu)) !void { + try expectEqual(Token(cpu).Tag.instruction, @as(Token(cpu).Tag, actual.data)); + try expectEqual(PayloadTag(cpu).irq, @as(PayloadTag(cpu), actual.data.instruction.payload)); const instr = actual.data.instruction; try expect_opt_value(expected.delay, instr.delay); @@ -1540,7 +1538,7 @@ fn expect_instr_irq(comptime format: assembler.Format, expected: ExpectedIrqInst const irq = instr.payload.irq; try expectEqual(expected.clear, irq.clear); try expectEqual(expected.wait, irq.wait); - switch (format) { + switch (cpu) { .RP2040 => { try expectEqual(expected.rel, irq.rel); }, @@ -1550,9 +1548,9 @@ fn expect_instr_irq(comptime format: assembler.Format, expected: ExpectedIrqInst } } -fn bounded_tokenize(comptime format: assembler.Format, source: []const u8) !std.BoundedArray(Token(format), 256) { +fn bounded_tokenize(comptime cpu: CPU, source: []const u8) !std.BoundedArray(Token(cpu), 256) { var diags: ?assembler.Diagnostics = null; - return tokenize(format, source, &diags, .{}) catch |err| if (diags) |d| blk: { + return tokenize(cpu, source, &diags, .{}) catch |err| if (diags) |d| blk: { std.log.err("error at index {}: {s}", .{ d.index, d.message.slice() }); break :blk err; } else err; @@ -1590,7 +1588,7 @@ test "tokenize.block comment" { } test "tokenize.code block" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, \\% c-sdk { \\ int foo; @@ -1602,14 +1600,14 @@ test "tokenize.code block" { } test "tokenize.directive.program" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".program arst"); try expect_program(format, "arst", tokens.get(0)); } } test "tokenize.directive.define" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".define symbol_name 1"); try expect_define(format, .{ .name = "symbol_name", @@ -1620,7 +1618,7 @@ test "tokenize.directive.define" { } test "tokenize.directive.define.public" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".define public symbol_name 0x1"); try expect_define(format, .{ .name = "symbol_name", @@ -1631,7 +1629,7 @@ test "tokenize.directive.define.public" { } test "tokenize.directive.define.with expression" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, \\.define symbol_name 0x1 \\.define something (symbol_name * 2) @@ -1652,98 +1650,98 @@ test "tokenize.directive.define.with expression" { } test "tokenize.directive.origin" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".origin 0x10"); try expect_origin(format, .{ .integer = 0x10 }, tokens.get(0)); } } test "tokenize.directive.side_set" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".side_set 1"); try expect_side_set(format, .{ .count = .{ .integer = 1 } }, tokens.get(0)); } } test "tokenize.directive.side_set.opt" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".side_set 1 opt"); try expect_side_set(format, .{ .count = .{ .integer = 1 }, .opt = true }, tokens.get(0)); } } test "tokenize.directive.side_set.pindirs" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".side_set 1 pindirs"); try expect_side_set(format, .{ .count = .{ .integer = 1 }, .pindir = true }, tokens.get(0)); } } test "tokenize.directive.wrap_target" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".wrap_target"); try expect_wrap_target(format, tokens.get(0)); } } test "tokenize.directive.wrap" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".wrap"); try expect_wrap(format, tokens.get(0)); } } test "tokenize.directive.lang_opt" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".lang_opt c flag foo"); try expect_lang_opt(format, .{ .lang = "c", .name = "flag", .option = "foo" }, tokens.get(0)); } } test "tokenize.directive.word" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, ".word 0xaaaa"); try expect_word(format, .{ .integer = 0xaaaa }, tokens.get(0)); } } test "tokenize.label" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, "my_label:"); try expect_label(format, .{ .name = "my_label" }, tokens.get(0)); } } test "tokenize.label.public" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, "public my_label:"); try expect_label(format, .{ .name = "my_label", .public = true }, tokens.get(0)); } } test "tokenize.instr.nop" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, "nop"); try expect_instr_nop(format, .{}, tokens.get(0)); } } test "tokenize.instr.jmp.label" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, "jmp my_label"); try expect_instr_jmp(format, .{ .target = "my_label" }, tokens.get(0)); } } test "tokenize.instr.jmp.value" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, "jmp 0x2"); try expect_instr_jmp(format, .{ .target = "0x2" }, tokens.get(0)); } } test "tokenize.instr.jmp.conditions" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const Condition = Token(format).Instruction.Jmp.Condition; const cases = std.StaticStringMap(Condition).initComptime(.{ .{ "!x", .x_is_zero }, @@ -1764,7 +1762,7 @@ test "tokenize.instr.jmp.conditions" { } test "tokenize.instr.wait" { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { inline for (.{ "gpio", "pin", "irq" }) |source| { const tokens = try bounded_tokenize(format, comptime std.fmt.comptimePrint("wait 0 {s} 1", .{source})); try expect_instr_wait(format, .{ @@ -1957,7 +1955,7 @@ test "tokenize.instr.irq" { }); inline for (comptime modes.keys(), comptime modes.values(), 0..) |key, value, num| { - inline for (comptime .{ assembler.Format.RP2040, assembler.Format.RP2350 }) |format| { + inline for (comptime .{ CPU.RP2040, CPU.RP2350 }) |format| { const tokens = try bounded_tokenize(format, comptime std.fmt.comptimePrint("irq {s} {}", .{ key, num, diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/common.zig b/port/raspberrypi/rp2xxx/src/hal/pio/common.zig index 4b4d1851..86113356 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/common.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/common.zig @@ -2,31 +2,41 @@ const std = @import("std"); const assert = std.debug.assert; const microzig = @import("microzig"); -const cpu = @import("../compatibility.zig").cpu; +const CPU = @import("../cpu.zig").CPU; pub const PIO = microzig.chip.types.peripherals.PIO0; pub const PIO0 = microzig.chip.peripherals.PIO0; pub const PIO1 = microzig.chip.peripherals.PIO1; pub const assembler = @import("assembler.zig"); -const compatibility = @import("../compatibility.zig"); const encoder = @import("assembler/encoder.zig"); const gpio = @import("../gpio.zig"); const hw = @import("../hw.zig"); -// TODO: This is CPU specific -pub const Instruction = encoder.Instruction(assembler.cpuToFormat(compatibility.cpu)); +const Instruction = encoder.Instruction; pub const Program = assembler.Program; // global state for keeping track of used things -var used_instruction_space = switch (cpu) { - .RP2040 => [_]u32{ 0, 0 }, - .RP2350 => [_]u32{ 0, 0, 0 }, -}; -var claimed_state_machines = switch (cpu) { - .RP2040 => [_]u4{ 0, 0 }, - .RP2350 => [_]u4{ 0, 0, 0 }, -}; +fn UsedInstructionSpace(cpu: CPU) type { + switch (cpu) { + .RP2040 => return struct { + pub var val = [_]u32{ 0, 0 }; + }, + .RP2350 => return struct { + pub var val = [_]u32{ 0, 0, 0 }; + }, + } +} +fn ClaimedStateMachines(cpu: CPU) type { + switch (cpu) { + .RP2040 => return struct { + pub var val = [_]u4{ 0, 0 }; + }, + .RP2350 => return struct { + pub var val = [_]u4{ 0, 0, 0 }; + }, + } +} pub const Fifo = enum { tx, @@ -111,7 +121,7 @@ pub const PinMappingOptions = struct { in_base: u5 = 0, }; -pub fn PioImpl(EnumType: type) type { +pub fn PioImpl(EnumType: type, cpu: CPU) type { return struct { pub fn get_instruction_memory(self: EnumType) *volatile [32]u32 { const regs = self.get_regs(); @@ -123,7 +133,7 @@ pub fn PioImpl(EnumType: type) type { if (origin != offset) return false; - const used_mask = used_instruction_space[@intFromEnum(self)]; + const used_mask = UsedInstructionSpace(cpu).val[@intFromEnum(self)]; const program_mask = program.get_mask(); // We can add the program if the masks don't overlap, if there is @@ -153,7 +163,7 @@ pub fn PioImpl(EnumType: type) type { instruction_memory[i] = insn; const program_mask = program.get_mask(); - used_instruction_space[@intFromEnum(self)] |= program_mask << offset; + UsedInstructionSpace(cpu).val[@intFromEnum(self)] |= program_mask << offset; } /// Public functions will need to lock independently, so only exposing this function for now @@ -170,11 +180,11 @@ pub fn PioImpl(EnumType: type) type { // TODO: const lock = hw.Lock.claim() // defer lock.unlock(); - const claimed_mask = claimed_state_machines[@intFromEnum(self)]; + const claimed_mask = ClaimedStateMachines(cpu).val[@intFromEnum(self)]; return for (0..4) |i| { const sm_mask = (@as(u4, 1) << @as(u2, @intCast(i))); if (0 == (claimed_mask & sm_mask)) { - claimed_state_machines[@intFromEnum(self)] |= sm_mask; + ClaimedStateMachines(cpu).val[@intFromEnum(self)] |= sm_mask; break @as(StateMachine, @enumFromInt(i)); } } else error.NoSpace; @@ -471,7 +481,7 @@ pub fn PioImpl(EnumType: type) type { self: EnumType, sm: StateMachine, initial_pc: u5, - options: StateMachineInitOptions, + options: StateMachineInitOptions(cpu), ) void { // Halt the machine, set some sensible defaults self.sm_set_enabled(sm, false); @@ -486,7 +496,7 @@ pub fn PioImpl(EnumType: type) type { // Finally, clear some internal SM state self.sm_restart(sm); self.sm_clkdiv_restart(sm); - self.sm_exec(sm, Instruction{ + self.sm_exec(sm, Instruction(cpu){ .tag = .jmp, .delay_side_set = 0, @@ -499,7 +509,7 @@ pub fn PioImpl(EnumType: type) type { }); } - pub fn sm_exec(self: EnumType, sm: StateMachine, instruction: Instruction) void { + pub fn sm_exec(self: EnumType, sm: StateMachine, instruction: Instruction(cpu)) void { const sm_regs = self.get_sm_regs(sm); sm_regs.instr.raw = @as(u16, @bitCast(instruction)); } @@ -508,7 +518,7 @@ pub fn PioImpl(EnumType: type) type { self: EnumType, sm: StateMachine, program: Program, - options: LoadAndStartProgramOptions, + options: LoadAndStartProgramOptions(cpu), ) !void { const expected_side_set_pins = if (program.side_set) |side_set| if (side_set.optional) @@ -554,57 +564,63 @@ pub fn PioImpl(EnumType: type) type { }; } -pub const ShiftOptions = switch (cpu) { - .RP2040 => struct { - autopush: bool = false, - autopull: bool = false, - in_shiftdir: Direction = .right, - out_shiftdir: Direction = .right, - /// 0 means full 32-bits - push_threshold: u5 = 0, - /// 0 means full 32-bits - pull_threshold: u5 = 0, - join_tx: bool = false, - join_rx: bool = false, - - pub const Direction = enum(u1) { - left, - right, - }; - }, - .RP2350 => struct { - autopush: bool = false, - autopull: bool = false, - in_shiftdir: Direction = .right, - out_shiftdir: Direction = .right, - /// 0 means full 32-bits - push_threshold: u5 = 0, - /// 0 means full 32-bits - pull_threshold: u5 = 0, - join_tx: bool = false, - join_rx: bool = false, - - fjoin_rx_get: bool = false, - fjoin_rx_put: bool = false, - in_count: u5 = 0, - - pub const Direction = enum(u1) { - left, - right, - }; - }, -}; +pub fn ShiftOptions(cpu: CPU) type { + return switch (cpu) { + .RP2040 => struct { + autopush: bool = false, + autopull: bool = false, + in_shiftdir: Direction = .right, + out_shiftdir: Direction = .right, + /// 0 means full 32-bits + push_threshold: u5 = 0, + /// 0 means full 32-bits + pull_threshold: u5 = 0, + join_tx: bool = false, + join_rx: bool = false, + + pub const Direction = enum(u1) { + left, + right, + }; + }, + .RP2350 => struct { + autopush: bool = false, + autopull: bool = false, + in_shiftdir: Direction = .right, + out_shiftdir: Direction = .right, + /// 0 means full 32-bits + push_threshold: u5 = 0, + /// 0 means full 32-bits + pull_threshold: u5 = 0, + join_tx: bool = false, + join_rx: bool = false, + + fjoin_rx_get: bool = false, + fjoin_rx_put: bool = false, + in_count: u5 = 0, + + pub const Direction = enum(u1) { + left, + right, + }; + }, + }; +} -pub const StateMachineInitOptions = struct { - clkdiv: ClkDivOptions = .{}, - pin_mappings: PinMappingOptions = .{}, - exec: ExecOptions = .{}, - shift: ShiftOptions = .{}, -}; +pub fn StateMachineInitOptions(cpu: CPU) type { + return struct { + clkdiv: ClkDivOptions = .{}, + pin_mappings: PinMappingOptions = .{}, + exec: ExecOptions = .{}, + shift: ShiftOptions(cpu) = .{}, + }; +} -pub const LoadAndStartProgramOptions = struct { - clkdiv: ClkDivOptions, - shift: ShiftOptions = .{}, - pin_mappings: PinMappingOptions = .{}, - exec: ExecOptions = .{}, -}; +pub fn LoadAndStartProgramOptions(cpu: CPU) type { + return struct { + clkdiv: ClkDivOptions, + shift: ShiftOptions(cpu) = .{}, + pin_mappings: PinMappingOptions = .{}, + exec: ExecOptions = .{}, + }; +} diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig b/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig index 2b8144d8..62c87f28 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/rp2040.zig @@ -13,6 +13,7 @@ pub const Pio = enum(u1) { pio0 = 0, pio1 = 1, + const PioImpl = common.PioImpl(Pio, .RP2040); pub fn get_regs(self: Pio) *volatile common.PIO { return switch (self) { .pio0 => common.PIO0, @@ -20,7 +21,7 @@ pub const Pio = enum(u1) { }; } - pub const get_instruction_memory = common.PioImpl(Pio).get_instruction_memory; + pub const get_instruction_memory = PioImpl.get_instruction_memory; pub fn gpio_init(self: Pio, pin: gpio.Pin) void { pin.set_function(switch (self) { @@ -29,15 +30,15 @@ pub const Pio = enum(u1) { }); } - pub const can_add_program_at_offset = common.PioImpl(Pio).can_add_program_at_offset; - pub const find_offset_for_program = common.PioImpl(Pio).find_offset_for_program; - pub const add_program_at_offset_unlocked = common.PioImpl(Pio).add_program_at_offset_unlocked; - pub const add_program = common.PioImpl(Pio).add_program; - pub const claim_unused_state_machine = common.PioImpl(Pio).claim_unused_state_machine; - pub const get_sm_regs = common.PioImpl(Pio).get_sm_regs; - pub const get_irq_regs = common.PioImpl(Pio).get_irq_regs; - pub const sm_set_clkdiv = common.PioImpl(Pio).sm_set_clkdiv; - pub const sm_set_exec_options = common.PioImpl(Pio).sm_set_exec_options; + pub const can_add_program_at_offset = PioImpl.can_add_program_at_offset; + pub const find_offset_for_program = PioImpl.find_offset_for_program; + pub const add_program_at_offset_unlocked = PioImpl.add_program_at_offset_unlocked; + pub const add_program = PioImpl.add_program; + pub const claim_unused_state_machine = PioImpl.claim_unused_state_machine; + pub const get_sm_regs = PioImpl.get_sm_regs; + pub const get_irq_regs = PioImpl.get_irq_regs; + pub const sm_set_clkdiv = PioImpl.sm_set_clkdiv; + pub const sm_set_exec_options = PioImpl.sm_set_exec_options; pub fn sm_set_shift_options(self: Pio, sm: common.StateMachine, options: common.ShiftOptions) void { const sm_regs = self.get_sm_regs(sm); @@ -57,19 +58,19 @@ pub const Pio = enum(u1) { }); } - pub const sm_set_pin_mappings = common.PioImpl(Pio).sm_set_pin_mappings; - pub const sm_set_pindir = common.PioImpl(Pio).sm_set_pindir; - pub const sm_set_pin = common.PioImpl(Pio).sm_set_pin; - pub const sm_get_rx_fifo = common.PioImpl(Pio).sm_get_rx_fifo; - pub const sm_is_rx_fifo_empty = common.PioImpl(Pio).sm_is_rx_fifo_empty; - pub const sm_blocking_read = common.PioImpl(Pio).sm_blocking_read; - pub const sm_read = common.PioImpl(Pio).sm_read; - pub const sm_is_tx_fifo_full = common.PioImpl(Pio).sm_is_tx_fifo_full; - pub const sm_get_tx_fifo = common.PioImpl(Pio).sm_get_tx_fifo; - pub const sm_write = common.PioImpl(Pio).sm_write; - pub const sm_blocking_write = common.PioImpl(Pio).sm_blocking_write; - pub const sm_set_enabled = common.PioImpl(Pio).sm_set_enabled; - pub const sm_clear_debug = common.PioImpl(Pio).sm_clear_debug; + pub const sm_set_pin_mappings = PioImpl.sm_set_pin_mappings; + pub const sm_set_pindir = PioImpl.sm_set_pindir; + pub const sm_set_pin = PioImpl.sm_set_pin; + pub const sm_get_rx_fifo = PioImpl.sm_get_rx_fifo; + pub const sm_is_rx_fifo_empty = PioImpl.sm_is_rx_fifo_empty; + pub const sm_blocking_read = PioImpl.sm_blocking_read; + pub const sm_read = PioImpl.sm_read; + pub const sm_is_tx_fifo_full = PioImpl.sm_is_tx_fifo_full; + pub const sm_get_tx_fifo = PioImpl.sm_get_tx_fifo; + pub const sm_write = PioImpl.sm_write; + pub const sm_blocking_write = PioImpl.sm_blocking_write; + pub const sm_set_enabled = PioImpl.sm_set_enabled; + pub const sm_clear_debug = PioImpl.sm_clear_debug; /// changing the state of fifos will clear them pub fn sm_clear_fifos(self: Pio, sm: common.StateMachine) void { @@ -93,12 +94,12 @@ pub const Pio = enum(u1) { xor_shiftctrl.write(mask); } - pub const sm_fifo_level = common.PioImpl(Pio).sm_fifo_level; - pub const sm_clear_interrupt = common.PioImpl(Pio).sm_clear_interrupt; - pub const sm_enable_interrupt = common.PioImpl(Pio).sm_enable_interrupt; - pub const sm_restart = common.PioImpl(Pio).sm_restart; - pub const sm_clkdiv_restart = common.PioImpl(Pio).sm_clkdiv_restart; - pub const sm_init = common.PioImpl(Pio).sm_init; - pub const sm_exec = common.PioImpl(Pio).sm_exec; - pub const sm_load_and_start_program = common.PioImpl(Pio).sm_load_and_start_program; + pub const sm_fifo_level = PioImpl.sm_fifo_level; + pub const sm_clear_interrupt = PioImpl.sm_clear_interrupt; + pub const sm_enable_interrupt = PioImpl.sm_enable_interrupt; + pub const sm_restart = PioImpl.sm_restart; + pub const sm_clkdiv_restart = PioImpl.sm_clkdiv_restart; + pub const sm_init = PioImpl.sm_init; + pub const sm_exec = PioImpl.sm_exec; + pub const sm_load_and_start_program = PioImpl.sm_load_and_start_program; }; diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig b/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig index ceb3e6ba..49e9f8b9 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/rp2350.zig @@ -16,6 +16,8 @@ pub const Pio = enum(u2) { pio1 = 1, pio2 = 2, + const PioImpl = common.PioImpl(Pio, .RP2350); + pub fn get_regs(self: Pio) *volatile common.PIO { return switch (self) { .pio0 => common.PIO0, @@ -24,7 +26,7 @@ pub const Pio = enum(u2) { }; } - pub const get_instruction_memory = common.PioImpl(Pio).get_instruction_memory; + pub const get_instruction_memory = PioImpl.get_instruction_memory; pub fn gpio_init(self: Pio, pin: gpio.Pin) void { pin.set_function(switch (self) { @@ -34,15 +36,15 @@ pub const Pio = enum(u2) { }); } - pub const can_add_program_at_offset = common.PioImpl(Pio).can_add_program_at_offset; - pub const find_offset_for_program = common.PioImpl(Pio).find_offset_for_program; - pub const add_program_at_offset_unlocked = common.PioImpl(Pio).add_program_at_offset_unlocked; - pub const add_program = common.PioImpl(Pio).add_program; - pub const claim_unused_state_machine = common.PioImpl(Pio).claim_unused_state_machine; - pub const get_sm_regs = common.PioImpl(Pio).get_sm_regs; - pub const get_irq_regs = common.PioImpl(Pio).get_irq_regs; - pub const sm_set_clkdiv = common.PioImpl(Pio).sm_set_clkdiv; - pub const sm_set_exec_options = common.PioImpl(Pio).sm_set_exec_options; + pub const can_add_program_at_offset = PioImpl.can_add_program_at_offset; + pub const find_offset_for_program = PioImpl.find_offset_for_program; + pub const add_program_at_offset_unlocked = PioImpl.add_program_at_offset_unlocked; + pub const add_program = PioImpl.add_program; + pub const claim_unused_state_machine = PioImpl.claim_unused_state_machine; + pub const get_sm_regs = PioImpl.get_sm_regs; + pub const get_irq_regs = PioImpl.get_irq_regs; + pub const sm_set_clkdiv = PioImpl.sm_set_clkdiv; + pub const sm_set_exec_options = PioImpl.sm_set_exec_options; pub fn sm_set_shift_options(self: Pio, sm: common.StateMachine, options: common.ShiftOptions) void { const sm_regs = self.get_sm_regs(sm); @@ -66,19 +68,19 @@ pub const Pio = enum(u2) { }); } - pub const sm_set_pin_mappings = common.PioImpl(Pio).sm_set_pin_mappings; - pub const sm_set_pindir = common.PioImpl(Pio).sm_set_pindir; - pub const sm_set_pin = common.PioImpl(Pio).sm_set_pin; - pub const sm_get_rx_fifo = common.PioImpl(Pio).sm_get_rx_fifo; - pub const sm_is_rx_fifo_empty = common.PioImpl(Pio).sm_is_rx_fifo_empty; - pub const sm_blocking_read = common.PioImpl(Pio).sm_blocking_read; - pub const sm_read = common.PioImpl(Pio).sm_read; - pub const sm_is_tx_fifo_full = common.PioImpl(Pio).sm_is_tx_fifo_full; - pub const sm_get_tx_fifo = common.PioImpl(Pio).sm_get_tx_fifo; - pub const sm_write = common.PioImpl(Pio).sm_write; - pub const sm_blocking_write = common.PioImpl(Pio).sm_blocking_write; - pub const sm_set_enabled = common.PioImpl(Pio).sm_set_enabled; - pub const sm_clear_debug = common.PioImpl(Pio).sm_clear_debug; + pub const sm_set_pin_mappings = PioImpl.sm_set_pin_mappings; + pub const sm_set_pindir = PioImpl.sm_set_pindir; + pub const sm_set_pin = PioImpl.sm_set_pin; + pub const sm_get_rx_fifo = PioImpl.sm_get_rx_fifo; + pub const sm_is_rx_fifo_empty = PioImpl.sm_is_rx_fifo_empty; + pub const sm_blocking_read = PioImpl.sm_blocking_read; + pub const sm_read = PioImpl.sm_read; + pub const sm_is_tx_fifo_full = PioImpl.sm_is_tx_fifo_full; + pub const sm_get_tx_fifo = PioImpl.sm_get_tx_fifo; + pub const sm_write = PioImpl.sm_write; + pub const sm_blocking_write = PioImpl.sm_blocking_write; + pub const sm_set_enabled = PioImpl.sm_set_enabled; + pub const sm_clear_debug = PioImpl.sm_clear_debug; /// changing the state of fifos will clear them pub fn sm_clear_fifos(self: Pio, sm: common.StateMachine) void { @@ -105,12 +107,12 @@ pub const Pio = enum(u2) { xor_shiftctrl.write(mask); } - pub const sm_fifo_level = common.PioImpl(Pio).sm_fifo_level; - pub const sm_clear_interrupt = common.PioImpl(Pio).sm_clear_interrupt; - pub const sm_enable_interrupt = common.PioImpl(Pio).sm_enable_interrupt; - pub const sm_restart = common.PioImpl(Pio).sm_restart; - pub const sm_clkdiv_restart = common.PioImpl(Pio).sm_clkdiv_restart; - pub const sm_init = common.PioImpl(Pio).sm_init; - pub const sm_exec = common.PioImpl(Pio).sm_exec; - pub const sm_load_and_start_program = common.PioImpl(Pio).sm_load_and_start_program; + pub const sm_fifo_level = PioImpl.sm_fifo_level; + pub const sm_clear_interrupt = PioImpl.sm_clear_interrupt; + pub const sm_enable_interrupt = PioImpl.sm_enable_interrupt; + pub const sm_restart = PioImpl.sm_restart; + pub const sm_clkdiv_restart = PioImpl.sm_clkdiv_restart; + pub const sm_init = PioImpl.sm_init; + pub const sm_exec = PioImpl.sm_exec; + pub const sm_load_and_start_program = PioImpl.sm_load_and_start_program; };