diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig index fe6d077ca..32e8e2212 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/comparison_tests.zig @@ -41,6 +41,7 @@ fn pio_comparison(comptime source: []const u8) !void { } fn pio_comparison_chip(comptime chip: Chip, comptime source: []const u8) !void { + @setEvalBranchQuota(100_000); const output = comptime assembler.assemble(chip, source, .{}); try std.testing.expect(output.programs.len > 0); @@ -58,131 +59,105 @@ fn pio_comparison_chip(comptime chip: Chip, comptime source: []const u8) !void { } test "pio.comparison.addition" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/addition.pio")); } test "pio.comparison.apa102" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/apa102.pio")); } test "pio.comparison.blink" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/blink.pio")); } test "pio.comparison.clocked_input" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/clocked_input.pio")); } test "pio.comparison.differential_manchester" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/differential_manchester.pio")); } test "pio.comparison.hello" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/hello.pio")); } test "pio.comparison.hub75" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/hub75.pio")); } test "pio.comparison.i2c" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/i2c.pio")); } test "pio.comparison.irq" { - @setEvalBranchQuota(100_000); try pio_comparison_chip(.RP2350, @embedFile("comparison_tests/irq.pio")); } test "pio.comparison.manchester_encoding" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/manchester_encoding.pio")); } test "pio.comparison.movrx" { - @setEvalBranchQuota(100_000); try pio_comparison_chip(.RP2350, @embedFile("comparison_tests/movrx.pio")); } test "pio.comparison.nec_carrier_burst" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/nec_carrier_burst.pio")); } test "pio.comparison.nec_carrier_control" { - @setEvalBranchQuota(100_000); try pio_comparison(@embedFile("comparison_tests/nec_carrier_control.pio")); } test "pio.comparison.nec_receive" { - @setEvalBranchQuota(12_000); try pio_comparison(@embedFile("comparison_tests/nec_receive.pio")); } test "pio.comparison.pio_serialiser" { - @setEvalBranchQuota(3_000); try pio_comparison(@embedFile("comparison_tests/pio_serialiser.pio")); } test "pio.comparison.pwm" { - @setEvalBranchQuota(6_000); try pio_comparison(@embedFile("comparison_tests/pwm.pio")); } test "pio.comparison.quadrature_encoder" { - @setEvalBranchQuota(21_000); try pio_comparison(@embedFile("comparison_tests/quadrature_encoder.pio")); } test "pio.comparison.resistor_dac" { - @setEvalBranchQuota(3_000); try pio_comparison(@embedFile("comparison_tests/resistor_dac.pio")); } test "pio.comparison.spi" { - @setEvalBranchQuota(26_000); try pio_comparison(@embedFile("comparison_tests/spi.pio")); } test "pio.comparison.squarewave" { - @setEvalBranchQuota(3_000); try pio_comparison(@embedFile("comparison_tests/squarewave.pio")); } test "pio.comparison.squarewave_fast" { - @setEvalBranchQuota(3_000); try pio_comparison(@embedFile("comparison_tests/squarewave_fast.pio")); } test "pio.comparison.squarewave_wrap" { - @setEvalBranchQuota(3_000); try pio_comparison(@embedFile("comparison_tests/squarewave_wrap.pio")); } test "pio.comparison.st7789_lcd" { - @setEvalBranchQuota(6_000); try pio_comparison(@embedFile("comparison_tests/st7789_lcd.pio")); } test "pio.comparison.uart_rx" { - @setEvalBranchQuota(12_000); try pio_comparison(@embedFile("comparison_tests/uart_rx.pio")); } test "pio.comparison.uart_tx" { - @setEvalBranchQuota(7_000); try pio_comparison(@embedFile("comparison_tests/uart_tx.pio")); } test "pio.comparison.ws2812" { - @setEvalBranchQuota(12_000); try pio_comparison(@embedFile("comparison_tests/ws2812.pio")); } diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig index cbb3b6ee3..4051ca7e6 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig @@ -181,20 +181,19 @@ pub fn Encoder(comptime chip: Chip, comptime options: Options) type { break :outer error.DefineNotFound; }, - .expression => |expr_str| { + .expression => |expr_str| outer: { const expr = try Expression.tokenize(expr_str, index, diags); const result = try expr.evaluate(define_lists, diags); if (result < 0 or result > std.math.maxInt(T)) { diags.* = Diagnostics.init( index, "value of {} does not fit in a u{}", - .{ - result, @bitSizeOf(T), - }, + .{ result, @bitSizeOf(T) }, ); + break :outer error.TooBig; } - return @as(T, @intCast(result)); + break :outer @as(T, @intCast(result)); }, }; } @@ -462,20 +461,25 @@ pub fn Encoder(comptime chip: Chip, comptime options: Options) type { } fn calc_delay_side_set( - program_settings: ?SideSet, + sideset_settings: ?SideSet, side_set_opt: ?u5, delay_opt: ?u5, ) !u5 { - // TODO: error for side_set/delay collision const delay: u5 = if (delay_opt) |delay| delay else 0; - return if (program_settings) |settings| - if (settings.optional) - if (side_set_opt) |side_set| - 0x10 | (side_set << @as(u3, 4) - settings.count) | delay + const bits_needed = std.math.log2_int_ceil(u6, @as(u6, delay) + 1); + + return if (sideset_settings) |sideset| + if (sideset.optional) + if (sideset.count + bits_needed > 4) + error.SideSetDelayCollision + else if (side_set_opt) |side_set| + 0x10 | (side_set << @as(u3, 4) - sideset.count) | delay else delay + else if (sideset.count + bits_needed > 5) + error.SideSetDelayCollision else - (side_set_opt.? << @as(u3, 5) - settings.count) | delay + (side_set_opt.? << @as(u3, 5) - sideset.count) | delay else delay; } @@ -680,6 +684,7 @@ pub fn Instruction(comptime chip: Chip) type { const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectEqualStrings = std.testing.expectEqualStrings; +const expectError = std.testing.expectError; fn encode_bounded_output_impl(comptime chip: Chip, source: []const u8, diags: *?assembler.Diagnostics) !Encoder(chip, .{}).Output { const tokens = try tokenizer.tokenize(chip, source, diags, .{}); @@ -690,7 +695,7 @@ fn encode_bounded_output_impl(comptime chip: Chip, source: []const u8, diags: *? fn encode_bounded_output(comptime chip: Chip, source: []const u8) !Encoder(chip, .{}).Output { var diags: ?assembler.Diagnostics = null; return encode_bounded_output_impl(chip, source, &diags) catch |err| if (diags) |d| blk: { - std.log.err("error at index {}: {s}", .{ d.index, d.message.slice() }); + std.log.info("error at index {}: {s}", .{ d.index, d.message.slice() }); break :blk err; } else err; } @@ -1021,6 +1026,14 @@ test "encode.evaluate.bit reversal" { try expectEqual(@as(i128, 0x80000000), output.global_defines.get(0).value); } +test "encode.evaluate.value size" { + const bits = encode_bounded_output(.RP2040, + \\.program delay_too_big + \\nop [32] + ); + try expectError(error.TooBig, bits); +} + test "encode.jmp.label" { const output = try encode_bounded_output(.RP2040, \\.program arst @@ -1104,6 +1117,55 @@ test "encode.jmp.label origin" { } } +test "encode.error.sideset delay collision" { + const collision = encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 2 + \\nop side 3 [8] + ); + try expectError(error.SideSetDelayCollision, collision); + + const collision2 = encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 1 + \\nop side 3 [31] + ); + try expectError(error.SideSetDelayCollision, collision2); + + const collision3 = encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 1 opt + \\nop side 3 [31] + ); + try expectError(error.SideSetDelayCollision, collision3); + + _ = try encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 2 + \\nop side 3 [7] + ); + + _ = try encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\nop [31] + ); +} + +test "encode.error.sideset opt delay collision" { + const collision = encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 2, opt + \\nop side 3 [4] + ); + try expectError(error.SideSetDelayCollision, collision); + + _ = try encode_bounded_output(.RP2040, + \\.program sideset_delay_collision + \\.side_set 2, opt + \\nop side 3 [3] + ); +} + //test "encode.error.duplicated program name" {} //test "encode.error.duplicated define" {} //test "encode.error.multiple side_set" {}