diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15ef70c..98bdee9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,14 +14,9 @@ jobs: with: python-version: '3.10' - run: pip install ruamel.yaml pytest pytest-cov - - name: Unit tests - run: pytest python/tests/unit/ -v - - name: Unit coverage - run: pytest --cov=python/lira python/tests/unit/ --cov-report=term - - name: Integration tests - run: pytest python/tests/integration/ -v - - name: Diff integration output vs reference - run: diff python/tests/integration/integration.yaml tests/integration/reference.yaml + - run: pip install -e python/ + - name: Run Python tests (unit, integration, coverage) + run: bash tests/scripts/python.sh ruby-tests: runs-on: ubuntu-latest @@ -35,18 +30,8 @@ jobs: python-version: '3.10' - run: pip install ruamel.yaml - run: gem install minitest simplecov - - name: Unit tests - run: | - ruby -I ruby -I ruby/lib ruby/tests/unit/test_ir_ser_txt.rb - ruby -I ruby -I ruby/lib ruby/tests/unit/test_arch_ser_yaml.rb - ruby -I ruby -I ruby/lib ruby/tests/unit/test_ir_builder.rb - - name: Unit coverage - run: | - ruby -r simplecov -I ruby -I ruby/lib -e 'SimpleCov.start; Dir["ruby/tests/unit/*.rb"].each { |f| require_relative f }' - - name: Integration tests - run: ruby -I ruby -I ruby/lib ruby/tests/integration/test_integration.rb - - name: Diff integration output vs reference - run: diff ruby/tests/integration/integration.yaml tests/integration/reference.yaml + - name: Run Ruby tests (unit, integration, coverage) + run: bash tests/scripts/ruby.sh rust-tests: runs-on: ubuntu-latest @@ -56,11 +41,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.10' + - run: sudo apt-get update && sudo apt-get install -y z3 - run: pip install ruamel.yaml - - name: Integration tests - run: cd rust && cargo test -p lira-tests --test integration - - name: Diff integration output vs reference - run: diff rust/tests/integration/integration.yaml tests/integration/reference.yaml + - name: Run Rust tests (integration, with coverage) + run: bash tests/scripts/rust.sh cross-language: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 915133f..85ca188 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ htmlcov/ *.log .env build/ +tmp/ diff --git a/python/lira/__init__.py b/python/lira/__init__.py index ea7988d..5b84bd5 100644 --- a/python/lira/__init__.py +++ b/python/lira/__init__.py @@ -6,5 +6,5 @@ Instruction, InstructionEncoding, Snippet, SystemRegister, SystemRegisterField, TableInt, ) -from .arch_ser_yaml import write_arch, read_arch +from .arch_ser_yaml import write_arch, read_arch, copy_arch from .ir_ops import BaseOp diff --git a/python/lira/arch_ser_yaml.py b/python/lira/arch_ser_yaml.py index 6151ed7..ff6d7a0 100644 --- a/python/lira/arch_ser_yaml.py +++ b/python/lira/arch_ser_yaml.py @@ -55,3 +55,7 @@ def read_arch(filepath: Path) -> Arch: with open(filepath, 'r', encoding='utf-8') as f: data = yaml.load(f) return from_serializable(Arch, data) + + +def copy_arch(path_input: Path, path_output: Path) -> None: + write_arch(read_arch(path_input), path_output) diff --git a/python/tests/integration/copy_.py b/python/tests/integration/copy_.py new file mode 100644 index 0000000..98d869e --- /dev/null +++ b/python/tests/integration/copy_.py @@ -0,0 +1,14 @@ +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[3] +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + +from python.lira.arch_ser_yaml import copy_arch + + +if __name__ == '__main__': + if len(sys.argv) != 3: + sys.exit('Usage: copy_.py ') + copy_arch(Path(sys.argv[1]), Path(sys.argv[2])) diff --git a/python/tests/integration/integration.yaml b/python/tests/integration/integration.yaml deleted file mode 100644 index cd13447..0000000 --- a/python/tests/integration/integration.yaml +++ /dev/null @@ -1,859 +0,0 @@ -name: TargetArch -attributes: [] -register_files: - - name: XRegs - attributes: [] - reg_size: - lanes_base: 32 - lanes_mult: - regs: - - name: x0 - attributes: - - zero - - name: x1 - attributes: [] - - name: x2 - attributes: [] - - name: x3 - attributes: [] - - name: x4 - attributes: [] - - name: x5 - attributes: [] - - name: x6 - attributes: [] - - name: x7 - attributes: [] - - name: x8 - attributes: [] - - name: SpecialRegs - attributes: [] - reg_size: - lanes_base: 32 - lanes_mult: - regs: - - name: pc - attributes: - - pc -system_registers: [] -environment_functions: - - name: sysCall - attributes: [] - inputs: [] - outputs: [] - - name: writeMem16 - attributes: [] - inputs: - - 32 - - 16 - outputs: [] - - name: readMem16 - attributes: [] - inputs: - - 32 - outputs: - - 16 - - name: getPC - attributes: [] - inputs: [] - outputs: - - 32 - - name: setPC - attributes: [] - inputs: - - 32 - outputs: [] -tables_int: [] -operations: - - name: add_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 32 - semantic_base: :add - semantic_func: - semantic_func_128: - semantic_table: - - name: lsr_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 32 - semantic_base: :lsr - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_5 - attributes: [] - inputs: - - 32 - outputs: - - 5 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_5_to_32 - attributes: [] - inputs: - - 5 - outputs: - - 32 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_1_to_32 - attributes: [] - inputs: - - 1 - outputs: - - 32 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: lsl_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 32 - semantic_base: :lsl - semantic_func: - semantic_func_128: - semantic_table: - - name: orr_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 32 - semantic_base: :orr - semantic_func: - semantic_func_128: - semantic_table: - - name: and_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 32 - semantic_base: :and - semantic_func: - semantic_func_128: - semantic_table: - - name: eq_32 - attributes: [] - inputs: - - 32 - - 32 - outputs: - - 1 - semantic_base: :eq - semantic_func: - semantic_func_128: - semantic_table: - - name: select_32 - attributes: [] - inputs: - - 1 - - 32 - - 32 - outputs: - - 32 - semantic_base: :select - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_1 - attributes: [] - inputs: - - 32 - outputs: - - 1 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_1_to_13 - attributes: [] - inputs: - - 1 - outputs: - - 13 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_13_to_32 - attributes: [] - inputs: - - 13 - outputs: - - 32 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_6 - attributes: [] - inputs: - - 32 - outputs: - - 6 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_6_to_13 - attributes: [] - inputs: - - 6 - outputs: - - 13 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_4 - attributes: [] - inputs: - - 32 - outputs: - - 4 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_4_to_13 - attributes: [] - inputs: - - 4 - outputs: - - 13 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_13 - attributes: [] - inputs: - - 32 - outputs: - - 13 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_sign_13_to_32 - attributes: [] - inputs: - - 13 - outputs: - - 32 - semantic_base: :extend_sign - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_12 - attributes: [] - inputs: - - 32 - outputs: - - 12 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_sign_12_to_32 - attributes: [] - inputs: - - 12 - outputs: - - 32 - semantic_base: :extend_sign - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_16 - attributes: [] - inputs: - - 32 - outputs: - - 16 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extract_low_32_to_7 - attributes: [] - inputs: - - 32 - outputs: - - 7 - semantic_base: :extract_low - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_7_to_12 - attributes: [] - inputs: - - 7 - outputs: - - 12 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_12_to_32 - attributes: [] - inputs: - - 12 - outputs: - - 32 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_5_to_12 - attributes: [] - inputs: - - 5 - outputs: - - 12 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_sign_16_to_32 - attributes: [] - inputs: - - 16 - outputs: - - 32 - semantic_base: :extend_sign - semantic_func: - semantic_func_128: - semantic_table: - - name: extend_zero_16_to_32 - attributes: [] - inputs: - - 16 - outputs: - - 32 - semantic_base: :extend_zero - semantic_func: - semantic_func_128: - semantic_table: -snippets: - - name: decode_0 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 20; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 5 _t5 = op extract_low_32_to_5 _t4; - 1 32 _t6 = op extend_zero_5_to_32 _t5; - 1 = output 0 _t6; - - name: decode_1 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 15; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 5 _t5 = op extract_low_32_to_5 _t4; - 1 32 _t6 = op extend_zero_5_to_32 _t5; - 1 = output 0 _t6; - - name: decode_2 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 7; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 5 _t5 = op extract_low_32_to_5 _t4; - 1 32 _t6 = op extend_zero_5_to_32 _t5; - 1 = output 0 _t6; - - name: encode_0 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 51; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 32 _t10 = const 11; - 1 32 _t11 = op lsl_32 _t3 _t10; - 1 32 _t12 = op orr_32 _t9 _t11; - 1 1 _t13 = const 0; - 1 32 _t14 = op extend_zero_1_to_32 _t13; - 1 32 _t15 = const 14; - 1 32 _t16 = op lsl_32 _t14 _t15; - 1 32 _t17 = op orr_32 _t12 _t16; - 1 32 _t18 = const 19; - 1 32 _t19 = op lsl_32 _t2 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 32 _t21 = const 24; - 1 32 _t22 = op lsl_32 _t1 _t21; - 1 32 _t23 = op orr_32 _t20 _t22; - 1 1 _t24 = const 0; - 1 32 _t25 = op extend_zero_1_to_32 _t24; - 1 32 _t26 = const 31; - 1 32 _t27 = op lsl_32 _t25 _t26; - 1 32 _t28 = op orr_32 _t23 _t27; - 1 = output 0 _t28; - - name: constraint_0 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 4261441663; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 51; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: decode_3 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 31; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 1 _t5 = op extract_low_32_to_1 _t4; - 1 13 _t6 = op extend_zero_1_to_13 _t5; - 1 32 _t8 = const 12; - 1 32 _t9 = op extend_zero_13_to_32 _t6; - 1 32 _t10 = op lsl_32 _t9 _t8; - 1 32 _t12 = const 7; - 1 32 _t13 = op lsr_32 _t1 _t12; - 1 1 _t14 = op extract_low_32_to_1 _t13; - 1 13 _t15 = op extend_zero_1_to_13 _t14; - 1 32 _t17 = const 11; - 1 32 _t18 = op extend_zero_13_to_32 _t15; - 1 32 _t19 = op lsl_32 _t18 _t17; - 1 32 _t21 = op orr_32 _t10 _t19; - 1 32 _t23 = const 25; - 1 32 _t24 = op lsr_32 _t1 _t23; - 1 6 _t25 = op extract_low_32_to_6 _t24; - 1 13 _t26 = op extend_zero_6_to_13 _t25; - 1 32 _t28 = const 5; - 1 32 _t29 = op extend_zero_13_to_32 _t26; - 1 32 _t30 = op lsl_32 _t29 _t28; - 1 32 _t32 = op orr_32 _t21 _t30; - 1 32 _t34 = const 8; - 1 32 _t35 = op lsr_32 _t1 _t34; - 1 4 _t36 = op extract_low_32_to_4 _t35; - 1 13 _t37 = op extend_zero_4_to_13 _t36; - 1 32 _t39 = const 1; - 1 32 _t40 = op extend_zero_13_to_32 _t37; - 1 32 _t41 = op lsl_32 _t40 _t39; - 1 32 _t43 = op orr_32 _t32 _t41; - 1 13 _t45 = op extract_low_32_to_13 _t43; - 1 32 _t46 = op extend_sign_13_to_32 _t45; - 1 = output 0 _t46; - - name: encode_1 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 99; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 1 _t10 = const 0; - 1 32 _t11 = op extend_zero_1_to_32 _t10; - 1 32 _t12 = const 14; - 1 32 _t13 = op lsl_32 _t11 _t12; - 1 32 _t14 = op orr_32 _t9 _t13; - 1 32 _t15 = const 19; - 1 32 _t16 = op lsl_32 _t2 _t15; - 1 32 _t17 = op orr_32 _t14 _t16; - 1 32 _t18 = const 24; - 1 32 _t19 = op lsl_32 _t3 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 = output 0 _t20; - - name: constraint_1 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 28799; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 99; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: decode_4 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 20; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 12 _t5 = op extract_low_32_to_12 _t4; - 1 32 _t6 = op extend_sign_12_to_32 _t5; - 1 = output 0 _t6; - - name: encode_2 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 103; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 32 _t10 = const 11; - 1 32 _t11 = op lsl_32 _t3 _t10; - 1 32 _t12 = op orr_32 _t9 _t11; - 1 1 _t13 = const 0; - 1 32 _t14 = op extend_zero_1_to_32 _t13; - 1 32 _t15 = const 14; - 1 32 _t16 = op lsl_32 _t14 _t15; - 1 32 _t17 = op orr_32 _t12 _t16; - 1 32 _t18 = const 19; - 1 32 _t19 = op lsl_32 _t2 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 32 _t21 = const 31; - 1 32 _t22 = op lsl_32 _t1 _t21; - 1 32 _t23 = op orr_32 _t20 _t22; - 1 = output 0 _t23; - - name: constraint_2 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 28799; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 103; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: decode_5 - seq: | - 1 32 _t1 = input 0; - 1 32 _t3 = const 25; - 1 32 _t4 = op lsr_32 _t1 _t3; - 1 7 _t5 = op extract_low_32_to_7 _t4; - 1 12 _t6 = op extend_zero_7_to_12 _t5; - 1 32 _t8 = const 5; - 1 32 _t9 = op extend_zero_12_to_32 _t6; - 1 32 _t10 = op lsl_32 _t9 _t8; - 1 32 _t12 = const 7; - 1 32 _t13 = op lsr_32 _t1 _t12; - 1 5 _t14 = op extract_low_32_to_5 _t13; - 1 12 _t15 = op extend_zero_5_to_12 _t14; - 1 32 _t17 = op extend_zero_12_to_32 _t15; - 1 32 _t18 = op orr_32 _t10 _t17; - 1 12 _t20 = op extract_low_32_to_12 _t18; - 1 32 _t21 = op extend_sign_12_to_32 _t20; - 1 = output 0 _t21; - - name: encode_3 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 35; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 1 _t10 = const 1; - 1 32 _t11 = op extend_zero_1_to_32 _t10; - 1 32 _t12 = const 14; - 1 32 _t13 = op lsl_32 _t11 _t12; - 1 32 _t14 = op orr_32 _t9 _t13; - 1 32 _t15 = const 19; - 1 32 _t16 = op lsl_32 _t2 _t15; - 1 32 _t17 = op orr_32 _t14 _t16; - 1 32 _t18 = const 24; - 1 32 _t19 = op lsl_32 _t3 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 = output 0 _t20; - - name: constraint_3 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 28799; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 4131; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: encode_4 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 3; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 32 _t10 = const 11; - 1 32 _t11 = op lsl_32 _t3 _t10; - 1 32 _t12 = op orr_32 _t9 _t11; - 1 1 _t13 = const 1; - 1 32 _t14 = op extend_zero_1_to_32 _t13; - 1 32 _t15 = const 14; - 1 32 _t16 = op lsl_32 _t14 _t15; - 1 32 _t17 = op orr_32 _t12 _t16; - 1 32 _t18 = const 19; - 1 32 _t19 = op lsl_32 _t2 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 32 _t21 = const 31; - 1 32 _t22 = op lsl_32 _t1 _t21; - 1 32 _t23 = op orr_32 _t20 _t22; - 1 = output 0 _t23; - - name: constraint_4 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 28799; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 4099; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: encode_5 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = input 1; - 1 32 _t3 = input 2; - 1 32 _t4 = const 0; - 1 1 _t5 = const 3; - 1 32 _t6 = op extend_zero_1_to_32 _t5; - 1 32 _t7 = const 6; - 1 32 _t8 = op lsl_32 _t6 _t7; - 1 32 _t9 = op orr_32 _t4 _t8; - 1 32 _t10 = const 11; - 1 32 _t11 = op lsl_32 _t3 _t10; - 1 32 _t12 = op orr_32 _t9 _t11; - 1 1 _t13 = const 5; - 1 32 _t14 = op extend_zero_1_to_32 _t13; - 1 32 _t15 = const 14; - 1 32 _t16 = op lsl_32 _t14 _t15; - 1 32 _t17 = op orr_32 _t12 _t16; - 1 32 _t18 = const 19; - 1 32 _t19 = op lsl_32 _t2 _t18; - 1 32 _t20 = op orr_32 _t17 _t19; - 1 32 _t21 = const 31; - 1 32 _t22 = op lsl_32 _t1 _t21; - 1 32 _t23 = op orr_32 _t20 _t22; - 1 = output 0 _t23; - - name: constraint_5 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 28799; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 20483; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; - - name: constraint_6 - seq: | - 1 32 _t1 = input 0; - 1 32 _t2 = const 4294967295; - 1 32 _t3 = op and_32 _t1 _t2; - 1 32 _t4 = const 115; - 1 1 _t5 = op eq_32 _t3 _t4; - 1 = output 0 _t5; -instructions: - - name: add - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - rs2 - - rs1 - - rd - encoding: - encoded_size: 32 - const_encoding_part: 51 - const_mask: 4261441663 - decode: - - decode_0 - - decode_1 - - decode_2 - encode: encode_0 - constraint_decode: constraint_0 - constraint_encode: '' - semantic: | - 1 32 _t3 = input 1; - 1 32 _t4 = read XRegs _t3; - 1 32 _t7 = input 0; - 1 32 _t8 = read XRegs _t7; - 1 32 _t10 = op add_32 _t4 _t8; - 1 32 _t11 = input 2; - 1 = write XRegs _t11 _t10; - - name: beq - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - imm - - rs1 - - rs2 - encoding: - encoded_size: 32 - const_encoding_part: 99 - const_mask: 28799 - decode: - - decode_3 - - decode_1 - - decode_0 - encode: encode_1 - constraint_decode: constraint_1 - constraint_encode: '' - semantic: | - 1 32 _t3 = input 1; - 1 32 _t4 = read XRegs _t3; - 1 32 _t6 = input 2; - 1 32 _t7 = read XRegs _t6; - 1 1 _t8 = op eq_32 _t4 _t7; - 1 32 _t10 = env getPC; - 1 32 _t11 = input 0; - 1 32 _t12 = op add_32 _t10 _t11; - 1 32 _t14 = const 4; - 1 32 _t15 = op add_32 _t10 _t14; - 1 32 _t17 = op select_32 _t8 _t12 _t15; - 1 = env setPC _t17; - - name: jalr - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - imm - - rs1 - - rd - encoding: - encoded_size: 32 - const_encoding_part: 103 - const_mask: 28799 - decode: - - decode_4 - - decode_1 - - decode_2 - encode: encode_2 - constraint_decode: constraint_2 - constraint_encode: '' - semantic: | - 1 32 _t2 = env getPC; - 1 32 _t3 = const 4; - 1 32 _t4 = op add_32 _t2 _t3; - 1 32 _t8 = input 1; - 1 32 _t9 = read XRegs _t8; - 1 32 _t10 = input 0; - 1 32 _t11 = op add_32 _t9 _t10; - 1 32 _t13 = const -2; - 1 32 _t14 = op and_32 _t11 _t13; - 1 = env setPC _t14; - 1 32 _t15 = input 2; - 1 = write XRegs _t15 _t4; - - name: sh - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - imm - - rs1 - - rs2 - encoding: - encoded_size: 32 - const_encoding_part: 4131 - const_mask: 28799 - decode: - - decode_5 - - decode_1 - - decode_0 - encode: encode_3 - constraint_decode: constraint_3 - constraint_encode: '' - semantic: | - 1 32 _t3 = input 1; - 1 32 _t4 = read XRegs _t3; - 1 32 _t5 = input 0; - 1 32 _t6 = op add_32 _t4 _t5; - 1 32 _t9 = input 2; - 1 32 _t10 = read XRegs _t9; - 1 32 _t11 = const 0; - 1 32 _t12 = op lsr_32 _t10 _t11; - 1 16 _t13 = op extract_low_32_to_16 _t12; - 1 = env writeMem16 _t6 _t13; - - name: lh - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - imm - - rs1 - - rd - encoding: - encoded_size: 32 - const_encoding_part: 4099 - const_mask: 28799 - decode: - - decode_4 - - decode_1 - - decode_2 - encode: encode_4 - constraint_decode: constraint_4 - constraint_encode: '' - semantic: | - 1 32 _t3 = input 1; - 1 32 _t4 = read XRegs _t3; - 1 32 _t5 = input 0; - 1 32 _t6 = op add_32 _t4 _t5; - 1 16 _t8 = env readMem16 _t6; - 1 32 _t10 = op extend_sign_16_to_32 _t8; - 1 32 _t11 = input 2; - 1 = write XRegs _t11 _t10; - - name: lhu - attributes: [] - operand_sizes: - - 32 - - 32 - - 32 - operand_names: - - imm - - rs1 - - rd - encoding: - encoded_size: 32 - const_encoding_part: 20483 - const_mask: 28799 - decode: - - decode_4 - - decode_1 - - decode_2 - encode: encode_5 - constraint_decode: constraint_5 - constraint_encode: '' - semantic: | - 1 32 _t3 = input 1; - 1 32 _t4 = read XRegs _t3; - 1 32 _t5 = input 0; - 1 32 _t6 = op add_32 _t4 _t5; - 1 16 _t8 = env readMem16 _t6; - 1 32 _t10 = op extend_zero_16_to_32 _t8; - 1 32 _t11 = input 2; - 1 = write XRegs _t11 _t10; - - name: ecall - attributes: [] - operand_sizes: [] - operand_names: [] - encoding: - encoded_size: 32 - const_encoding_part: 115 - const_mask: 4294967295 - decode: [] - encode: '' - constraint_decode: constraint_6 - constraint_encode: '' - semantic: | - 1 = env sysCall; diff --git a/python/tests/integration/test_integration.py b/python/tests/integration/test_integration.py index 6f79da7..3bbc0c5 100644 --- a/python/tests/integration/test_integration.py +++ b/python/tests/integration/test_integration.py @@ -11,10 +11,11 @@ def test_integration(): ref_arch = arch_ser_yaml.read_arch(REFERENCE) - output = PROJECT_ROOT / "python" / "tests" / "integration" / "integration.yaml" + output = PROJECT_ROOT / "tmp" / "integration.yaml" + output.parent.mkdir(exist_ok=True) raw = output.with_suffix(".raw.yaml") try: - arch_ser_yaml.write_arch(ref_arch, raw) + arch_ser_yaml.copy_arch(REFERENCE, raw) subprocess.run( [sys.executable, str(CANONICALIZE), str(raw), str(output)], check=True ) diff --git a/ruby/lira/arch_ser_yaml.rb b/ruby/lira/arch_ser_yaml.rb index ba68c65..6ab6b44 100644 --- a/ruby/lira/arch_ser_yaml.rb +++ b/ruby/lira/arch_ser_yaml.rb @@ -56,5 +56,9 @@ def read_arch(filepath) data = YAML.load_file(filepath) from_serializable(Arch, data) end + + def copy_arch(src, dst) + write_arch(read_arch(src), dst) + end end end diff --git a/ruby/tests/integration/copy.rb b/ruby/tests/integration/copy.rb new file mode 100644 index 0000000..8ee9742 --- /dev/null +++ b/ruby/tests/integration/copy.rb @@ -0,0 +1,10 @@ +$LOAD_PATH.unshift(File.expand_path('../..', __dir__)) +require 'lira' +include Lira + +if ARGV.length != 2 + $stderr.puts "Usage: #{$0} " + exit 1 +end + +ArchSerYaml.copy_arch(ARGV[0], ARGV[1]) diff --git a/ruby/tests/integration/test_integration.rb b/ruby/tests/integration/test_integration.rb index b838a0b..da6ce6d 100644 --- a/ruby/tests/integration/test_integration.rb +++ b/ruby/tests/integration/test_integration.rb @@ -1,13 +1,15 @@ $LOAD_PATH.unshift(File.expand_path('../..', __dir__)) require 'lira' require 'minitest/autorun' +require 'fileutils' include Lira PROJECT_ROOT = File.expand_path('../../..', __dir__) REFERENCE = File.join(PROJECT_ROOT, 'tests', 'integration', 'reference.yaml') CANONICALIZE = File.join(PROJECT_ROOT, 'tools', 'yaml_canonicalize.py') -OUTPUT = File.join(__dir__, 'integration.yaml') +OUTPUT = File.join(PROJECT_ROOT, 'tmp', 'integration.yaml') +FileUtils.mkdir_p(File.dirname(OUTPUT)) class TestIntegration < Minitest::Test def test_roundtrip_from_reference @@ -15,7 +17,7 @@ def test_roundtrip_from_reference raw = "#{OUTPUT}.raw" begin - ArchSerYaml.write_arch(ref_arch, raw) + ArchSerYaml.copy_arch(REFERENCE, raw) system('python3', CANONICALIZE, raw, OUTPUT) File.delete(raw) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 25f8382..5e47705 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -166,6 +166,14 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "copy" +version = "0.1.0" +dependencies = [ + "anyhow", + "lira", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -581,6 +589,7 @@ name = "lira-tests" version = "0.1.0" dependencies = [ "anyhow", + "copy", "lira", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f534875..43c02f4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "3" -members = ["lira", "lira_trs", "tests"] +members = ["lira", "lira_trs", "tests", "copy"] [workspace.dependencies] anyhow = "1.0.102" diff --git a/rust/copy/Cargo.toml b/rust/copy/Cargo.toml new file mode 100644 index 0000000..d3dc32e --- /dev/null +++ b/rust/copy/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "copy" +version = "0.1.0" +edition = "2024" + +[dependencies] +lira.path = "../lira" +anyhow = { workspace = true } diff --git a/rust/copy/src/lib.rs b/rust/copy/src/lib.rs new file mode 100644 index 0000000..6c92c9a --- /dev/null +++ b/rust/copy/src/lib.rs @@ -0,0 +1,5 @@ +use std::path::Path; + +pub fn copy_arch(src: &Path, dst: &Path) -> anyhow::Result<()> { + lira::Arch::read_yaml(src)?.write_yaml(dst) +} diff --git a/rust/copy/src/main.rs b/rust/copy/src/main.rs new file mode 100644 index 0000000..4ffffaf --- /dev/null +++ b/rust/copy/src/main.rs @@ -0,0 +1,5 @@ +fn main() -> anyhow::Result<()> { + let args: Vec<_> = std::env::args().collect(); + assert!(args.len() == 3, "Usage: copy "); + copy::copy_arch(std::path::Path::new(&args[1]), std::path::Path::new(&args[2])) +} diff --git a/rust/tests/Cargo.toml b/rust/tests/Cargo.toml index 8f595ab..26092f0 100644 --- a/rust/tests/Cargo.toml +++ b/rust/tests/Cargo.toml @@ -13,4 +13,5 @@ path = "integration/main.rs" [dependencies] lira = { path = "../lira" } +copy = { path = "../copy" } anyhow = { workspace = true } diff --git a/rust/tests/integration/main.rs b/rust/tests/integration/main.rs index 3d965a4..36e1810 100644 --- a/rust/tests/integration/main.rs +++ b/rust/tests/integration/main.rs @@ -19,13 +19,11 @@ fn test_roundtrip_from_reference() { .join("reference.yaml"); let ref_arch = Arch::read_yaml(&ref_path).unwrap(); - let output = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .join("integration") - .join("integration.yaml"); + let output = project_root().join("tmp").join("integration.yaml"); std::fs::create_dir_all(output.parent().unwrap()).ok(); let raw = output.with_extension("raw.yaml"); - ref_arch.write_yaml(&raw).unwrap(); + copy::copy_arch(&ref_path, &raw).unwrap(); let canonicalize = project_root().join("tools").join("yaml_canonicalize.py"); std::process::Command::new("python3") .arg(&canonicalize) diff --git a/tests/cross_language/test_cross.py b/tests/cross_language/test_cross.py index 88b9ebf..76b3d81 100644 --- a/tests/cross_language/test_cross.py +++ b/tests/cross_language/test_cross.py @@ -3,21 +3,24 @@ import pytest -sys.path.insert(0, str(Path(__file__).parent.parent.parent)) +ROOT = Path(__file__).parent.parent.parent +sys.path.insert(0, str(ROOT)) from python.lira import arch_ser_yaml CROSS_DIR = Path(__file__).parent -REFERENCE = Path(__file__).parent.parent / "integration" / "reference.yaml" +REFERENCE = CROSS_DIR.parent / "integration" / "reference.yaml" +TMP_DIR = ROOT / "tmp" +TMP_DIR.mkdir(exist_ok=True) -PY_OUT = CROSS_DIR / "py_native.yaml" -RB_OUT = CROSS_DIR / "rb_native.yaml" -RS_OUT = CROSS_DIR / "rs_native.yaml" +PY_OUT = TMP_DIR / "py_native.yaml" +RB_OUT = TMP_DIR / "rb_native.yaml" +RS_OUT = TMP_DIR / "rs_native.yaml" def test_python_write_and_self_read(): arch = arch_ser_yaml.read_arch(REFERENCE) - arch_ser_yaml.write_arch(arch, PY_OUT) + arch_ser_yaml.copy_arch(REFERENCE, PY_OUT) arch2 = arch_ser_yaml.read_arch(PY_OUT) assert arch == arch2 @@ -26,8 +29,8 @@ def test_python_reads_ruby(): if not RB_OUT.exists(): pytest.skip("rb_native.yaml not found") arch = arch_ser_yaml.read_arch(RB_OUT) - arch_ser_yaml.write_arch(arch, CROSS_DIR / "py_from_rb.yaml") - arch2 = arch_ser_yaml.read_arch(CROSS_DIR / "py_from_rb.yaml") + arch_ser_yaml.copy_arch(RB_OUT, TMP_DIR / "py_from_rb.yaml") + arch2 = arch_ser_yaml.read_arch(TMP_DIR / "py_from_rb.yaml") assert arch == arch2 @@ -35,6 +38,6 @@ def test_python_reads_rust(): if not RS_OUT.exists(): pytest.skip("rs_native.yaml not found") arch = arch_ser_yaml.read_arch(RS_OUT) - arch_ser_yaml.write_arch(arch, CROSS_DIR / "py_from_rs.yaml") - arch2 = arch_ser_yaml.read_arch(CROSS_DIR / "py_from_rs.yaml") + arch_ser_yaml.copy_arch(RS_OUT, TMP_DIR / "py_from_rs.yaml") + arch2 = arch_ser_yaml.read_arch(TMP_DIR / "py_from_rs.yaml") assert arch == arch2 diff --git a/tests/cross_language/test_cross.rb b/tests/cross_language/test_cross.rb index da42114..51e2ae4 100644 --- a/tests/cross_language/test_cross.rb +++ b/tests/cross_language/test_cross.rb @@ -2,20 +2,24 @@ $LOAD_PATH.unshift(File.expand_path('../..', __dir__)) require 'lira' require 'minitest/autorun' +require 'fileutils' include Lira +ROOT = File.expand_path('../..', __dir__) CROSS_DIR = File.expand_path(__dir__) REFERENCE = File.join(CROSS_DIR, '..', 'integration', 'reference.yaml') +TMP_DIR = File.join(ROOT, 'tmp') +FileUtils.mkdir_p(TMP_DIR) -RB_OUT = File.join(CROSS_DIR, 'rb_native.yaml') -PY_OUT = File.join(CROSS_DIR, 'py_native.yaml') -RS_OUT = File.join(CROSS_DIR, 'rs_native.yaml') +RB_OUT = File.join(TMP_DIR, 'rb_native.yaml') +PY_OUT = File.join(TMP_DIR, 'py_native.yaml') +RS_OUT = File.join(TMP_DIR, 'rs_native.yaml') class TestCrossLanguage < Minitest::Test def test_ruby_write_and_self_read arch = ArchSerYaml.read_arch(REFERENCE) - ArchSerYaml.write_arch(arch, RB_OUT) + ArchSerYaml.copy_arch(REFERENCE, RB_OUT) arch2 = ArchSerYaml.read_arch(RB_OUT) assert_equal arch, arch2 end @@ -23,16 +27,16 @@ def test_ruby_write_and_self_read def test_ruby_reads_python skip('py_native.yaml not found') unless File.exist?(PY_OUT) arch = ArchSerYaml.read_arch(PY_OUT) - ArchSerYaml.write_arch(arch, File.join(CROSS_DIR, 'rb_from_py.yaml')) - arch2 = ArchSerYaml.read_arch(File.join(CROSS_DIR, 'rb_from_py.yaml')) + ArchSerYaml.copy_arch(PY_OUT, File.join(TMP_DIR, 'rb_from_py.yaml')) + arch2 = ArchSerYaml.read_arch(File.join(TMP_DIR, 'rb_from_py.yaml')) assert_equal arch, arch2 end def test_ruby_reads_rust skip('rs_native.yaml not found') unless File.exist?(RS_OUT) arch = ArchSerYaml.read_arch(RS_OUT) - ArchSerYaml.write_arch(arch, File.join(CROSS_DIR, 'rb_from_rs.yaml')) - arch2 = ArchSerYaml.read_arch(File.join(CROSS_DIR, 'rb_from_rs.yaml')) + ArchSerYaml.copy_arch(RS_OUT, File.join(TMP_DIR, 'rb_from_rs.yaml')) + arch2 = ArchSerYaml.read_arch(File.join(TMP_DIR, 'rb_from_rs.yaml')) assert_equal arch, arch2 end end diff --git a/tests/cross_language/test_cross.rs b/tests/cross_language/test_cross.rs index 39e4c88..72eca08 100644 --- a/tests/cross_language/test_cross.rs +++ b/tests/cross_language/test_cross.rs @@ -2,20 +2,24 @@ use std::path::PathBuf; use lira::*; -fn cross_dir() -> PathBuf { +fn project_root() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .unwrap() .parent() .unwrap() - .join("tests") - .join("cross_language") + .to_path_buf() +} + +fn tmp_dir() -> PathBuf { + let dir = project_root().join("tmp"); + std::fs::create_dir_all(&dir).ok(); + dir } fn reference() -> PathBuf { - cross_dir() - .parent() - .unwrap() + project_root() + .join("tests") .join("integration") .join("reference.yaml") } @@ -23,21 +27,21 @@ fn reference() -> PathBuf { #[test] fn test_rust_write_and_self_read() { let arch = Arch::read_yaml(&reference()).unwrap(); - let out = cross_dir().join("rs_native.yaml"); - arch.write_yaml(&out).unwrap(); + let out = tmp_dir().join("rs_native.yaml"); + copy::copy_arch(&reference(), &out).unwrap(); let arch2 = Arch::read_yaml(&out).unwrap(); assert_eq!(arch, arch2); } #[test] fn test_rust_reads_python() { - let py_out = cross_dir().join("py_native.yaml"); + let py_out = tmp_dir().join("py_native.yaml"); if !py_out.exists() { return; } let arch = Arch::read_yaml(&py_out).unwrap(); - let tmp = cross_dir().join("rs_from_py.yaml"); - arch.write_yaml(&tmp).unwrap(); + let tmp = tmp_dir().join("rs_from_py.yaml"); + copy::copy_arch(&py_out, &tmp).unwrap(); let arch2 = Arch::read_yaml(&tmp).unwrap(); assert_eq!(arch, arch2); std::fs::remove_file(&tmp).ok(); @@ -45,13 +49,13 @@ fn test_rust_reads_python() { #[test] fn test_rust_reads_ruby() { - let rb_out = cross_dir().join("rb_native.yaml"); + let rb_out = tmp_dir().join("rb_native.yaml"); if !rb_out.exists() { return; } let arch = Arch::read_yaml(&rb_out).unwrap(); - let tmp = cross_dir().join("rs_from_rb.yaml"); - arch.write_yaml(&tmp).unwrap(); + let tmp = tmp_dir().join("rs_from_rb.yaml"); + copy::copy_arch(&rb_out, &tmp).unwrap(); let arch2 = Arch::read_yaml(&tmp).unwrap(); assert_eq!(arch, arch2); std::fs::remove_file(&tmp).ok(); diff --git a/tests/scripts/python.sh b/tests/scripts/python.sh new file mode 100644 index 0000000..dc856db --- /dev/null +++ b/tests/scripts/python.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -ex + +echo "=== Python tests ===" +pytest python/tests/unit/ -v +pytest --cov=python/lira python/tests/unit/ --cov-report=term +bash tests/scripts/round_trip.sh "python3 python/tests/integration/copy_.py" +pytest python/tests/integration/ -v diff --git a/tests/scripts/round_trip.sh b/tests/scripts/round_trip.sh new file mode 100644 index 0000000..65c58dd --- /dev/null +++ b/tests/scripts/round_trip.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +[ $# -eq 1 ] || { echo "Usage: $0 "; exit 1; } + +REF=tests/integration/reference.yaml + +mkdir -p tmp +$1 $REF tmp/raw1.yaml +$1 tmp/raw1.yaml tmp/raw2.yaml +# Round‑trip without canonicalization +diff tmp/raw1.yaml tmp/raw2.yaml +python3 tools/yaml_canonicalize.py tmp/raw1.yaml tmp/out.yaml +# Round‑trip with canonicalization +diff tmp/out.yaml $REF diff --git a/tests/scripts/ruby.sh b/tests/scripts/ruby.sh new file mode 100644 index 0000000..8b7c18c --- /dev/null +++ b/tests/scripts/ruby.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -ex + +echo "=== Ruby tests ===" +ruby -I ruby -I ruby/lib ruby/tests/unit/test_ir_ser_txt.rb +ruby -I ruby -I ruby/lib ruby/tests/unit/test_arch_ser_yaml.rb +ruby -I ruby -I ruby/lib ruby/tests/unit/test_ir_builder.rb +ruby -r simplecov -I ruby -I ruby/lib -e 'SimpleCov.start; Dir["ruby/tests/unit/*.rb"].each { |f| require_relative f }' +bash tests/scripts/round_trip.sh "ruby ruby/tests/integration/copy.rb" +ruby -I ruby -I ruby/lib ruby/tests/integration/test_integration.rb diff --git a/tests/scripts/rust.sh b/tests/scripts/rust.sh new file mode 100644 index 0000000..2cbe3dd --- /dev/null +++ b/tests/scripts/rust.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -ex + +echo "=== Rust tests ===" +cargo test --manifest-path rust/Cargo.toml +bash tests/scripts/round_trip.sh "cargo run --manifest-path rust/Cargo.toml --bin copy --"