Add pioasm test cases for error and valid scenarios

Introduces new test files for pioasm covering various error conditions (e.g., invalid FIFO usage, instruction limits, symbol errors, sideset configuration, pin config, and more) and valid output scenarios for expressions and language-specific symbol generation (Go, JSON, Python). These tests improve coverage and validation of pioasm's error handling and output formatting.
This commit is contained in:
Gonzalo Larralde 2026-01-09 02:38:01 -03:00
parent 67b2ab00e8
commit 9e58e8ac24
31 changed files with 558 additions and 0 deletions

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program fifo_autopush_incompatible
.fifo txput
.in 1 auto
in pins, 1
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.7-11: PIO version 1 is required for 'txput'
// 3 | .fifo txput
// | ^~~~~
//

View file

@ -0,0 +1,14 @@
// run: pioasm -v 1 input.pio
.program fifo_index_invalid
.pio_version 1
.fifo putget
mov rxfifo[8], isr
// -- Output
// Command: pioasm -v 1 input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.16: FIFO index myst be between 0 and 7
// 5 | mov rxfifo[8], isr
// | ^
//

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program circular_dependency
.define a b + 1
.define b a + 1
.word a
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.11: circular dependency in definition of 'a'; detected at input.pio:4.11)
// 5 | .word a
// | ^
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program delay_negative
nop [-1]
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.10-11: instruction delay must be positive
// 3 | nop [-1]
// | ^~
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program delay_sideset_limit
.side_set 5
nop side 0 [1]
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.17: the instruction delay limit is 0 because of the side set specified at input.pio:3.1-11
// 4 | nop side 0 [1]
// | ^
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program delay_too_large
nop [32]
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.10-11: instruction delay must be <= 31
// 3 | nop [32]
// | ^~
//

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program dup_symbol
start:
start:
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.1-5: label 'start' was already defined at input.pio:3.1-5
// 4 | start:
// | ^~~~~
//

View file

@ -0,0 +1,44 @@
// run: pioasm input.pio
.program over_limit
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:35.5-7: program instruction limit of 32 instruction(s) exceeded
// 35 | nop
// | ^~~
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program jmp_negative
jmp -1
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.9-10: jmp target address must be positive
// 3 | jmp -1
// | ^~
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program jmp_out_of_range
jmp 5
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.9: jmp target address 5 is beyond the end of the program
// 3 | jmp 5
// | ^
//

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program out_set_wait_invalid
out pins, 0
set pins, 32
wait 2 irq 0
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.15: 'out' bit count must be >= 1 and <= 32
// 3 | out pins, 0
// | ^
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_bits_negative
.side_set -1
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.11: syntax error, unexpected -, expecting ( or identifier or integer
// 3 | .side_set -1
// | ^
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_bits_optional_too_large
.side_set 5 opt
nop side 0
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.11: maximum number of side set bits with optional is 4
// 3 | .side_set 5 opt
// | ^
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_bits_too_large
.side_set 6
nop side 0
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.11: maximum number of side set bits is 5
// 3 | .side_set 6
// | ^
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_missing
.side_set 1
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.5-7: instruction requires 'side' to specify side set value for the instruction because non optional sideset was specified for the program at input.pio:3.1-11
// 4 | nop
// | ^~~
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_value_negative
.side_set 2
nop side -1
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.14: syntax error, unexpected -, expecting ( or identifier or integer
// 4 | nop side -1
// | ^
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program sideset_value_too_large
.side_set 2
nop side 4
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.14: the maximum side set value is 3 based on the configuration specified at input.pio:3.1-11
// 4 | nop side 4
// | ^
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program undefined_symbol
.word missing_symbol
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.11-24: undefined symbol 'missing_symbol'
// 3 | .word missing_symbol
// | ^~~~~~~~~~~~~~
//

View file

@ -0,0 +1,12 @@
// run: pioasm input.pio
.program word_too_large
.word 0x1ffff
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.5-17: .word value must be a positive 16 bit value
// 3 | .word 0x1ffff
// | ^~~~~~~~~~~~~
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program wrap_error
.wrap
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:3.1-5: .wrap cannot be placed before the first program instruction
// 3 | .wrap
// | ^~~~~
//

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program wrap_duplicate
nop
.wrap
.wrap
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.1-5: .wrap was already specified at input.pio:4.1-5
// 5 | .wrap
// | ^~~~~
//

View file

@ -0,0 +1,13 @@
// run: pioasm input.pio
.program wrap_target_after_end
nop
.wrap_target
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.1-12: .wrap_target cannot be placed after the last program instruction
// 4 | .wrap_target
// | ^~~~~~~~~~~~
//

View file

@ -0,0 +1,14 @@
// run: pioasm input.pio
.program wrap_target_duplicate
.wrap_target
nop
.wrap_target
// -- Output
// Command: pioasm input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.1-12: .wrap_target was already specified at input.pio:3.1-12
// 5 | .wrap_target
// | ^~~~~~~~~~~~
//

View file

@ -0,0 +1,14 @@
// run: pioasm -v 1 input.pio
.program mov_status_irq
.pio_version 1
.mov_status irq set 8
mov x, status
// -- Output
// Command: pioasm -v 1 input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.21: irq number should be >= 0 and <= 7
// 4 | .mov_status irq set 8
// | ^
//

View file

@ -0,0 +1,14 @@
// run: pioasm -v 1 input.pio
.program wait_gpio_conflict_high_then_low
.pio_version 1
wait 0 gpio 40
wait 0 gpio 0
// -- Output
// Command: pioasm -v 1 input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.17: absolute GPIO number must be must be >= 16 and <= 47 as a GPIO number >32 has already been used
// 5 | wait 0 gpio 0
// | ^
//

View file

@ -0,0 +1,14 @@
// run: pioasm -v 1 input.pio
.program wait_gpio_conflict_low_then_high
.pio_version 1
wait 0 gpio 0
wait 0 gpio 40
// -- Output
// Command: pioasm -v 1 input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:5.17-18: absolute GPIO number must be must be >= 0 and <= 31 as a GPIO number <16 has already been used
// 5 | wait 0 gpio 40
// | ^~
//

View file

@ -0,0 +1,13 @@
// run: pioasm -v 1 input.pio
.program wait_gpio_range
.pio_version 1
wait 0 gpio 48
// -- Output
// Command: pioasm -v 1 input.pio
// Exit code: 1
// Stdout:
// Stderr:
// input.pio:4.17-18: absolute GPIO number must be must be >= 0 and <= 47
// 4 | wait 0 gpio 48
// | ^~
//

View file

@ -0,0 +1,57 @@
// run: pioasm input.pio
.program unary_test
.define PUBLIC neg_val -5
.define PUBLIC rev_val ::1
start:
nop
// -- Output
// Command: pioasm input.pio
// Exit code: 0
// Stdout:
// // ------------------------------------------------------------------------ //
//?
// // ------------------------------------------------------------------------ //
//
// #pragma once
//
// #if !PICO_NO_HARDWARE
// #include "hardware/pio.h"
// #endif
//
// // ---------- //
// // unary_test //
// // ---------- //
//
// #define unary_test_wrap_target 0
// #define unary_test_wrap 0
// #define unary_test_pio_version 0
//
// #define unary_test_neg_val -5
// #define unary_test_rev_val -2147483648
//
// static const uint16_t unary_test_program_instructions[] = {
// // .wrap_target
// 0xa042, // 0: nop
// // .wrap
// };
//
// #if !PICO_NO_HARDWARE
// static const struct pio_program unary_test_program = {
// .instructions = unary_test_program_instructions,
// .length = 1,
// .origin = -1,
// .pio_version = unary_test_pio_version,
// #if PICO_PIO_VERSION > 0
// .used_gpio_ranges = 0x0
// #endif
// };
//
// static inline pio_sm_config unary_test_program_get_default_config(uint offset) {
// pio_sm_config c = pio_get_default_sm_config();
// sm_config_set_wrap(&c, offset + unary_test_wrap_target, offset + unary_test_wrap);
// return c;
// }
// #endif
//
//
// Stderr:

View file

@ -0,0 +1,40 @@
// run: pioasm -o go input.pio
.define PUBLIC global_const 7
.program format_test
public entry:
nop
%go {
package pioasmtest
// Custom Go block
%}
// -- Output
// Command: pioasm -o go input.pio
// Exit code: 0
// Stdout:
//?
//
// package pioasmtest
// // Custom Go block
// // format_test
//
// const format_testWrapTarget = 0
// const format_testWrap = 0
//
// const format_testoffset_entry = 0
//
// var format_testInstructions = []uint16{
// // .wrap_target
// 0xa042, // 0: nop
// // .wrap
// }
// const format_testOrigin = -1
// func format_testProgramDefaultConfig(offset uint8) pio.StateMachineConfig {
// cfg := pio.DefaultStateMachineConfig()
// cfg.SetWrap(offset+format_testWrapTarget, offset+format_testWrap)
// return cfg;
// }
//
// const global_const = 7
//
//
// Stderr:

View file

@ -0,0 +1,36 @@
// run: pioasm -o json input.pio
.define PUBLIC global_const 7
.program format_test
public entry:
nop
.lang_opt json foo = 1
// -- Output
// Command: pioasm -o json input.pio
// Exit code: 0
// Stdout:
// {
// "publicSymbols": {
// "global_const": 7
// },
// "programs": [
// {
// "name": "format_test",
// "wrapTarget": 0,
// "wrap": 0,
// "origin": -1,
// "sideset": {"size": 0, "optional": false, "pindirs": false},
// "publicSymbols": {
// },
// "publicLabels": {
// "entry": 0
// },
// "instructions": [
// {"hex": "A042"}
// ]
// }
// ]
// }
//
// Stderr:
// warning: json does not support output options; json lang_opt ignored.
//

View file

@ -0,0 +1,39 @@
// run: pioasm -o python input.pio
.define PUBLIC global_const 7
.program format_test
public entry:
nop
.lang_opt python in_shiftdir = right
%python {
# Custom python block
%}
// -- Output
// Command: pioasm -o python input.pio
// Exit code: 0
// Stdout:
// # ------------------------------------------------------------------------ #
//?
// # ------------------------------------------------------------------------ #
//
// import rp2
// from machine import Pin
// global_const = 7
//
// # ----------- #
// # format_test #
// # ----------- #
//
// format_test_offset_entry = 0
//
// @rp2.asm_pio(in_shiftdir=right)
// def format_test():
// wrap_target()
// nop() # 0
// wrap()
//
//
// # Custom python block
//
//
//
// Stderr: