diff --git a/.github/workflows/_runner-chimera.yml b/.github/workflows/_runner-chimera.yml index fbfe4480f1..14e80631d1 100644 --- a/.github/workflows/_runner-chimera.yml +++ b/.github/workflows/_runner-chimera.yml @@ -14,10 +14,7 @@ name: _runner-chimera docker-image: required: true type: string - test-names: - required: true - type: string - simulators: + pytest-marker: required: true type: string @@ -39,22 +36,11 @@ jobs: with: path: /app/.ccache key: ccache-ci - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" - simulators="${{inputs.simulators}}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache export CHIMERA_SDK_HOME=/app/install/chimera-sdk - echo "$simulators" | while IFS= read -r simulator; do - if [[ -n "$simulator" ]]; then - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test $testName using $simulator" - python testRunner_chimera.py -t Tests/$testName --simulator=$simulator - fi - done - fi - done + pytest test_platforms.py -v -n 4 -m "chimera and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-cortexm.yml b/.github/workflows/_runner-cortexm.yml index 70ee5b5d45..3fbdf0ee16 100644 --- a/.github/workflows/_runner-cortexm.yml +++ b/.github/workflows/_runner-cortexm.yml @@ -14,7 +14,7 @@ name: _runner-cortexm docker-image: required: true type: string - test-names: + pytest-marker: required: true type: string @@ -36,16 +36,10 @@ jobs: with: path: /app/.ccache key: ccache-ci - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test: $testName" - python testRunner_cortexm.py -t Tests/$testName - fi - done + pytest test_platforms.py -v -n 4 -m "cortexm and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-generic.yml b/.github/workflows/_runner-generic.yml index 50fa0f3a3b..6681cbac96 100644 --- a/.github/workflows/_runner-generic.yml +++ b/.github/workflows/_runner-generic.yml @@ -14,7 +14,7 @@ name: _runner-generic docker-image: required: true type: string - test-names: + pytest-marker: required: true type: string @@ -36,16 +36,10 @@ jobs: with: path: /app/.ccache key: ccache-ci - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test: $testName" - python testRunner_generic.py -t Tests/$testName - fi - done + pytest test_platforms.py -v -n 4 -m "generic and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-mempool.yml b/.github/workflows/_runner-mempool.yml index edd048ba9d..deb4809330 100644 --- a/.github/workflows/_runner-mempool.yml +++ b/.github/workflows/_runner-mempool.yml @@ -14,7 +14,7 @@ name: _runner-mempool docker-image: required: true type: string - test-names: + pytest-marker: required: true type: string @@ -36,16 +36,10 @@ jobs: with: path: /app/.ccache key: ccache-ci - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test: $testName" - python testRunner_mempool.py -t Tests/$testName - fi - done + pytest test_platforms.py -v -n 4 -m "mempool and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml b/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml deleted file mode 100644 index b1a8915319..0000000000 --- a/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml +++ /dev/null @@ -1,84 +0,0 @@ -# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - ---- -name: _runner-siracusa-neureka-tiled-sequential - -"on": - workflow_call: - inputs: - runner: - required: true - type: string - docker-image: - required: true - type: string - tests-config: - required: true - type: string - num-cores: - required: false - default: 8 - type: number - default-memory-level: - required: false - default: "L2" - type: string - double-buffer: - required: false - default: false - type: boolean - memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string - search-strategy: - required: false - default: "random-max" - type: string - neureka-wmem: - required: false - default: false - type: boolean - -jobs: - test-runner-siracusa-neureka-tiled: - runs-on: ${{ inputs.runner }} - container: - image: ${{ inputs.docker-image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Install jq - run: | - export DEBIAN_FRONTEND=noninteractive - apt-get update -y - apt-get install -y jq - - name: Cache ccache - uses: actions/cache/restore@v4 - with: - path: /app/.ccache - key: ccache-ci - - name: Run Tests - run: | - cd DeeployTest - echo '${{ inputs.tests-config }}' > tests.json - mkdir -p /app/.ccache - export CCACHE_DIR=/app/.ccache - - jq -c '.[]' tests.json | while read test; do - testName=$(echo "$test" | jq -r '.name') - L1_values=$(echo "$test" | jq -r '.L1[]') - for L1_value in $L1_values; do - echo "Running test: $testName with L1: $L1_value" - python testRunner_tiled_siracusa_w_neureka.py -t Tests/$testName --cores=${{ inputs.num-cores }} --l1 $L1_value --defaultMemLevel=${{ inputs.default-memory-level }} ${{ inputs.double-buffer && '--doublebuffer' || '' }} ${{ inputs.neureka-wmem && '--neureka-wmem' || '' }} --memAllocStrategy=${{ inputs.memory-allocation-strategy }} --searchStrategy=${{ inputs.search-strategy }} - done - done - - shell: bash diff --git a/.github/workflows/_runner-siracusa-neureka-tiled.yml b/.github/workflows/_runner-siracusa-neureka-tiled.yml index 3e613a84cb..b1f5f2fcb3 100644 --- a/.github/workflows/_runner-siracusa-neureka-tiled.yml +++ b/.github/workflows/_runner-siracusa-neureka-tiled.yml @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -name: _runner-siracusa-neureka-tiled +name: _runner-siracusa-neureka-tiled-sequential "on": workflow_call: @@ -14,44 +14,12 @@ name: _runner-siracusa-neureka-tiled docker-image: required: true type: string - test-name: + pytest-marker: required: true type: string - num-cores: - required: false - default: 8 - type: number - L1: - required: false - default: "[64000]" - type: string - default-memory-level: - required: false - default: "L2" - type: string - double-buffer: - required: false - default: false - type: boolean - memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string - search-strategy: - required: false - default: "random-max" - type: string - neureka-wmem: - required: false - default: false - type: boolean jobs: test-runner-siracusa-neureka-tiled: - strategy: - fail-fast: false - matrix: - L1: ${{ fromJSON(inputs.L1) }} runs-on: ${{ inputs.runner }} container: image: ${{ inputs.docker-image }} @@ -63,20 +31,10 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . - - name: Cache ccache - uses: actions/cache/restore@v4 - with: - path: /app/.ccache - key: ccache-ci - - name: Run Test - uses: nick-fields/retry@v3 - with: - timeout_minutes: 5 - max_attempts: 3 - retry_on: timeout - command: | - cd DeeployTest - mkdir -p /app/.ccache - export CCACHE_DIR=/app/.ccache - python testRunner_tiled_siracusa_w_neureka.py -t Tests/${{ inputs.test-name }} --cores=${{ inputs.num-cores }} --l1 ${{ matrix.L1 }} --defaultMemLevel=${{ inputs.default-memory-level }} ${{ inputs.double-buffer && '--doublebuffer' || '' }} ${{ inputs.neureka-wmem && '--neureka-wmem' || '' }} --memAllocStrategy=${{ inputs.memory-allocation-strategy }} --searchStrategy=${{ inputs.search-strategy }} - shell: bash + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. + run: | + cd DeeployTest + mkdir -p /app/.ccache + export CCACHE_DIR=/app/.ccache + pytest test_platforms.py -v -n 4 -m "siracusa_neureka_tiled and ${{ inputs.pytest-marker }}" + shell: bash diff --git a/.github/workflows/_runner-siracusa-tiled-sequential.yml b/.github/workflows/_runner-siracusa-tiled-sequential.yml deleted file mode 100644 index 056d8f0398..0000000000 --- a/.github/workflows/_runner-siracusa-tiled-sequential.yml +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - ---- -name: _runner-siracusa-tiled - -"on": - workflow_call: - inputs: - runner: - required: true - type: string - docker-image: - required: true - type: string - tests-config: - required: true - type: string - num-cores: - required: false - default: 8 - type: number - default-memory-level: - required: false - default: "L2" - type: string - double-buffer: - required: false - default: false - type: boolean - memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string - search-strategy: - required: false - default: "random-max" - type: string - -jobs: - test-runner-siracusa-tiled: - runs-on: ${{ inputs.runner }} - container: - image: ${{ inputs.docker-image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Install jq - run: | - export DEBIAN_FRONTEND=noninteractive - apt-get update -y - apt-get install -y jq - - name: Cache ccache - uses: actions/cache/restore@v4 - with: - path: /app/.ccache - key: ccache-ci - - name: Run Tests - run: | - cd DeeployTest - echo '${{ inputs.tests-config }}' > tests.json - mkdir -p /app/.ccache - export CCACHE_DIR=/app/.ccache - - jq -c '.[]' tests.json | while read test; do - testName=$(echo "$test" | jq -r '.name') - L1_values=$(echo "$test" | jq -r '.L1[]') - for L1_value in $L1_values; do - echo "Running test: $testName with L1: $L1_value" - python testRunner_tiled_siracusa.py -t Tests/$testName --cores=${{ inputs.num-cores }} --l1 $L1_value --defaultMemLevel=${{ inputs.default-memory-level }} ${{ inputs.double-buffer && '--doublebuffer' || '' }} --memAllocStrategy=${{ inputs.memory-allocation-strategy }} --searchStrategy=${{ inputs.search-strategy }} - done - done - shell: bash diff --git a/.github/workflows/_runner-siracusa-tiled.yml b/.github/workflows/_runner-siracusa-tiled.yml index f33836c6b8..ea9c8989af 100644 --- a/.github/workflows/_runner-siracusa-tiled.yml +++ b/.github/workflows/_runner-siracusa-tiled.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # # SPDX-License-Identifier: Apache-2.0 @@ -14,40 +14,12 @@ name: _runner-siracusa-tiled docker-image: required: true type: string - test-name: + pytest-marker: required: true type: string - num-cores: - required: false - default: 8 - type: number - L1: - required: false - default: "[64000]" - type: string - default-memory-level: - required: false - default: "L2" - type: string - double-buffer: - required: false - default: false - type: boolean - memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string - search-strategy: - required: false - default: "random-max" - type: string jobs: test-runner-siracusa-tiled: - strategy: - fail-fast: false - matrix: - L1: ${{ fromJSON(inputs.L1) }} runs-on: ${{ inputs.runner }} container: image: ${{ inputs.docker-image }} @@ -59,20 +31,8 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . - - name: Cache ccache - uses: actions/cache/restore@v4 - with: - path: /app/.ccache - key: ccache-ci - name: Run Test - uses: nick-fields/retry@v3 - with: - timeout_minutes: 15 - max_attempts: 3 - retry_on: timeout - command: | - cd DeeployTest - mkdir -p /app/.ccache - export CCACHE_DIR=/app/.ccache - python testRunner_tiled_siracusa.py -t Tests/${{ inputs.test-name }} --cores=${{ inputs.num-cores }} --l1 ${{ matrix.L1 }} --defaultMemLevel=${{ inputs.default-memory-level }} ${{ inputs.double-buffer && '--doublebuffer' || '' }} --memAllocStrategy=${{ inputs.memory-allocation-strategy }} --searchStrategy=${{ inputs.search-strategy }} - shell: bash + run: | + cd DeeployTest + pytest test_platforms.py -v -m "siracusa_tiled and ${{ inputs.pytest-marker }}" + shell: bash diff --git a/.github/workflows/_runner-siracusa.yml b/.github/workflows/_runner-siracusa.yml index 1972724e9c..eb9a098b5f 100644 --- a/.github/workflows/_runner-siracusa.yml +++ b/.github/workflows/_runner-siracusa.yml @@ -14,12 +14,10 @@ name: _runner-siracusa docker-image: required: true type: string - test-names: + test-type: required: true type: string - num-cores: - required: true - type: number + description: "Type of tests to run: kernels or models" jobs: test-runner-siracusa: @@ -41,14 +39,10 @@ jobs: key: ccache-ci - name: Run Test run: | - testNames="${{ inputs.test-names }}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test: $testName" - python testRunner_siracusa.py -t Tests/$testName --cores=${{ inputs.num-cores }} - fi - done + + # Run tests using pytest markers + pytest test_platforms.py::test_siracusa_${{ inputs.test-type }} -v -s shell: bash diff --git a/.github/workflows/_runner-snitch-tiled-sequential.yml b/.github/workflows/_runner-snitch-tiled-sequential.yml index 4128b13186..fbd5195b08 100644 --- a/.github/workflows/_runner-snitch-tiled-sequential.yml +++ b/.github/workflows/_runner-snitch-tiled-sequential.yml @@ -14,26 +14,7 @@ name: _runner-snitch-tiled-sequential docker-image: required: true type: string - tests-config: - required: true - type: string - num-cores: - required: false - default: 9 - type: number - default-memory-level: - required: false - default: "L2" - type: string - memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string - search-strategy: - required: false - default: "random-max" - type: string - simulators: + pytest-marker: required: true type: string @@ -50,33 +31,10 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . - - name: Install jq - run: | - export DEBIAN_FRONTEND=noninteractive - apt-get update -y - apt-get install -y jq - - name: Cache ccache - uses: actions/cache/restore@v4 - with: - path: /app/.ccache - key: ccache-ci - - name: Run Tests + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - simulators="${{inputs.simulators}}" cd DeeployTest - echo '${{ inputs.tests-config }}' > tests.json mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$simulators" | while IFS= read -r simulator; do - if [[ -n "$simulator" ]]; then - jq -c '.[]' tests.json | while read test; do - testName=$(echo "$test" | jq -r '.name') - L1_values=$(echo "$test" | jq -r '.L1[]') - for L1_value in $L1_values; do - echo "Running test: $testName with L1: $L1_value using $simulator" - python testRunner_tiled_snitch.py -t Tests/$testName --cores=${{ inputs.num-cores }} --simulator=$simulator --l1 $L1_value --defaultMemLevel=${{ inputs.default-memory-level }} --memAllocStrategy=${{ inputs.memory-allocation-strategy }} --searchStrategy=${{ inputs.search-strategy }} - done - done - fi - done + pytest test_platforms.py -v -n 4 -m "snitch_tiled and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-snitch.yml b/.github/workflows/_runner-snitch.yml index ab0ae55ed7..bc599e4fe7 100644 --- a/.github/workflows/_runner-snitch.yml +++ b/.github/workflows/_runner-snitch.yml @@ -14,13 +14,7 @@ name: _runner-snitch docker-image: required: true type: string - test-names: - required: true - type: string - num-cores: - required: true - type: number - simulators: + pytest-marker: required: true type: string @@ -42,21 +36,10 @@ jobs: with: path: /app/.ccache key: ccache-ci - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" - simulators="${{inputs.simulators}}" cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - echo "$simulators" | while IFS= read -r simulator; do - if [[ -n "$simulator" ]]; then - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test $testName using $simulator" - python testRunner_snitch.py -t Tests/$testName --simulator=$simulator --cores=${{ inputs.num-cores }} - fi - done - fi - done + pytest test_platforms.py -v -n 4 -m "snitch and ${{ inputs.pytest-marker }}" shell: bash diff --git a/.github/workflows/_runner-softhier.yml b/.github/workflows/_runner-softhier.yml index e06aea3b9b..b067664f40 100644 --- a/.github/workflows/_runner-softhier.yml +++ b/.github/workflows/_runner-softhier.yml @@ -14,7 +14,7 @@ name: _runner-softhier docker-image: required: true type: string - test-names: + pytest-marker: required: true type: string @@ -31,15 +31,11 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . - - name: Run Test + - name: Run Test # VJUNG: Run tests with 4 parallel threads as GitHub action VM has 4 cores. run: | - testNames="${{ inputs.test-names }}" export SOFTHIER_INSTALL_DIR=/app/install/softhier cd DeeployTest - echo "$testNames" | while IFS= read -r testName; do - if [[ -n "$testName" ]]; then - echo "Running test: $testName" - python testRunner_softhier.py -t Tests/$testName --toolchain=GCC - fi - done + mkdir -p /app/.ccache + export CCACHE_DIR=/app/.ccache + pytest test_platforms.py -v -n 4 -m "softhier and ${{ inputs.pytest-marker }}" --toolchain=GCC --toolchain-install-dir=$SOFTHIER_INSTALL_DIR/third_party/toolchain/install shell: bash diff --git a/.github/workflows/_select-env.yml b/.github/workflows/_select-env.yml index 1085c7eaa1..ba9c9d0c83 100644 --- a/.github/workflows/_select-env.yml +++ b/.github/workflows/_select-env.yml @@ -34,7 +34,7 @@ jobs: elif [[ "${{ github.ref_name }}" == "main" ]]; then IMAGE="ghcr.io/pulp-platform/deeploy:main" else - IMAGE="ghcr.io/pulp-platform/deeploy:devel" + IMAGE="ghcr.io/victor-jung/deeploy:pytest-migration" fi echo "image=${IMAGE}" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/ci-deeploy-testing.yml b/.github/workflows/ci-deeploy-testing.yml deleted file mode 100644 index c6e262ee40..0000000000 --- a/.github/workflows/ci-deeploy-testing.yml +++ /dev/null @@ -1,78 +0,0 @@ -# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - ---- -name: CI • Deeploy Testing - -"on": - push: - branches: - - "**" - tags: - - "v*.*.*" - pull_request: - workflow_dispatch: - inputs: - docker_image_deeploy: - description: "Deeploy Image to use" - required: false - default: "ghcr.io/pulp-platform/deeploy:devel" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - select-env: - uses: ./.github/workflows/_select-env.yml - with: - docker_image_deeploy: ${{ inputs.docker_image_deeploy }} - - generate-network-type-inference: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - strategy: - fail-fast: false - matrix: - include: - - name: fail-input0 - platform: Generic - test: Others/TypeInference - type_map: "A=int8_t B=int8_t C=int8_t" - offset_map: "A=0 B=0 C=0" - shouldFail: true - - name: fail-input2 - platform: Generic - test: Others/TypeInference - type_map: "A=int16_t B=int8_t C=int16_t" - offset_map: "A=0 B=0 C=0" - shouldFail: true - - name: pass - platform: Generic - test: Others/TypeInference - type_map: "A=int16_t B=int8_t C=int32_t" - offset_map: "A=0 B=0 C=0" - shouldFail: false - name: Test Type Inference (${{ matrix.name }}) - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python generateNetwork.py \ - -p ${{ matrix.platform }} \ - -t ./Tests/${{ matrix.test }} \ - -v \ - --input-type-map ${{ matrix.type_map }} \ - --input-offset-map ${{ matrix.offset_map }} \ - ${{ matrix.shouldFail && '--shouldFail' || '' }} diff --git a/.github/workflows/ci-deeploy.yml b/.github/workflows/ci-deeploy.yml index 02f3e03097..fc468306b1 100644 --- a/.github/workflows/ci-deeploy.yml +++ b/.github/workflows/ci-deeploy.yml @@ -43,7 +43,7 @@ jobs: shell: bash run: pip install -e . - deeploy-memory-allocation: + deeploy-internal-tests: needs: select-env runs-on: ${{ needs.select-env.outputs.runner }} container: @@ -56,183 +56,8 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . - - name: Run Test + - name: Run Internal Tests shell: bash run: | cd DeeployTest - python testMVP.py -t Tests/Models/CCT/FP32/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=75000 --memAllocStrategy=MiniMalloc - python testMVP.py -t Tests/Models/CCT/FP32/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=60000 --memAllocStrategy=MiniMalloc --shouldFail - python testMVP.py -t Tests/Models/CCT/FP32/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=90000 --memAllocStrategy=TetrisRandom - python testMVP.py -t Tests/Models/CCT/FP32/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=75000 --memAllocStrategy=TetrisRandom --shouldFail - - deeploy-state-serialization: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python deeployStateEqualityTest.py -t ./Tests/Models/CNN_Linear2 -p QEMU-ARM - python deeployStateEqualityTest.py -t ./Tests/Models/CNN_Linear2 -p Siracusa - python deeployStateEqualityTest.py -t ./Tests/Models/CNN_Linear2 -p MemPool - python deeployStateEqualityTest.py -t ./Tests/Models/CNN_Linear2 -p Generic - - deeploy-memory-level-extension: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testMemoryLevelExtension.py -t ./Tests/Models/CNN_Linear2 -p QEMU-ARM - python testMemoryLevelExtension.py -t ./Tests/Models/CNN_Linear2 -p Siracusa - python testMemoryLevelExtension.py -t ./Tests/Models/CNN_Linear2 -p MemPool - python testMemoryLevelExtension.py -t ./Tests/Models/CNN_Linear2 -p Generic - - deeploy-tiler-extension: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear2 - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear1 - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MatMul/Regular - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MaxPool - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear2 --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear1 --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MatMul/Regular --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MaxPool --l1 2000 --shouldFail - - deeploy-memory-allocation-extension: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear2 - python testTilerExtension.py -p Siracusa -t ./Tests/Models/CNN_Linear1 - python testTilerExtension.py -p Siracusa -t ./Tests/Models/miniMobileNet - python testTilerExtension.py -p Siracusa -t ./Tests/Models/miniMobileNetv2 - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MatMul/Regular - python testTilerExtension.py -p Siracusa -t ./Tests/Kernels/Integer/MaxPool - - deeploy-typing: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testTypes.py - - deeploy-debug: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testPrintInputOutputTransformation.py -p Generic -t ./Tests/Models/CNN_Linear2 - python testPrintInputOutputTransformation.py -p Siracusa -t ./Tests/Models/CNN_Linear2 - python testDebugPrintPass.py -p Generic -t ./Tests/Models/CNN_Linear2 - - deeploy-regex-matching: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testRegexMatching.py - - deeploy-test-dmas: - needs: select-env - runs-on: ${{ needs.select-env.outputs.runner }} - container: - image: ${{ needs.select-env.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - shell: bash - run: pip install -e . - - name: Run Test - shell: bash - run: | - cd DeeployTest - python testDmas.py + pytest -v -m deeploy_internal -n 4 diff --git a/.github/workflows/ci-platform-chimera.yml b/.github/workflows/ci-platform-chimera.yml index b07f5554d6..aad065ae78 100644 --- a/.github/workflows/ci-platform-chimera.yml +++ b/.github/workflows/ci-platform-chimera.yml @@ -35,7 +35,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/Integer/Add/Regular - simulators: | - gvsoc + pytest-marker: "kernels" diff --git a/.github/workflows/ci-platform-cortexm.yml b/.github/workflows/ci-platform-cortexm.yml index 614b734580..0e03e17d0b 100644 --- a/.github/workflows/ci-platform-cortexm.yml +++ b/.github/workflows/ci-platform-cortexm.yml @@ -35,18 +35,7 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/Integer/Add/Regular - Kernels/Integer/Add/MultIO - Kernels/Integer/Pad/Regular_1D - Kernels/Integer/Pad/Regular_2D - Kernels/Integer/MatMul/Regular - Kernels/Integer/MatMul/Add - Kernels/Integer/MaxPool - Kernels/Integer/Conv/Regular_2D_RQ - Kernels/Integer/ReduceSum - Kernels/Integer/ReduceMean - Kernels/Integer/Slice + pytest-marker: "kernels" cortexm-models: needs: select-env @@ -54,6 +43,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Models/CNN_Linear2 - Models/WaveFormer + pytest-marker: "models" diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml index 790637f4d4..83c191180f 100644 --- a/.github/workflows/ci-platform-generic.yml +++ b/.github/workflows/ci-platform-generic.yml @@ -35,89 +35,7 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/FP32/ReLU - Kernels/FP32/Softmax/Regular - - Kernels/FP32/Add/Regular - - Kernels/FP32/Conv/DW_2D_Bias - Kernels/FP32/Conv/DW_2D_NoBias - Kernels/FP32/Conv/DW_2D_ZeroValuedBias - - Kernels/FP32/Conv/Regular_2D_Bias - Kernels/FP32/Conv/Regular_2D_NoBias - Kernels/FP32/Conv/Regular_2D_ZeroValuedBias - - Kernels/FP32/Div - Kernels/FP32/GEMM/Regular - Kernels/FP32/MatMul - Kernels/FP32/MaxPool - Kernels/FP32/Mul - - Kernels/FP32/LayerNorm - Kernels/FP32/RMSNorm - - Kernels/FP32/Pow/Scalar - Kernels/FP32/Pow/Vector - - Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean - Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add - Kernels/FP32/ReduceMean/KeepDims/AllAxes - Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3 - Kernels/FP32/ReduceMean/KeepDims/Axes1_3 - Kernels/FP32/ReduceMean/KeepDims/Axes2_1 - Kernels/FP32/ReduceMean/KeepDims/Axis0 - Kernels/FP32/ReduceMean/KeepDims/Axis2 - Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add - - Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean - Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add - Kernels/FP32/ReduceMean/NoKeepDims/AllAxes - Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3 - Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3 - Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1 - Kernels/FP32/ReduceMean/NoKeepDims/Axis0 - Kernels/FP32/ReduceMean/NoKeepDims/Axis2 - Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add - - Kernels/FP32/Reshape/SkipConnection - Kernels/FP32/Sqrt - Kernels/FP32/Transpose - - Kernels/Integer/Softmax/Regular - - Kernels/Integer/Add/MultIO - Kernels/Integer/Add/Regular - - Kernels/Integer/Conv/DW_1D - Kernels/Integer/Conv/Regular_1D - - Kernels/Integer/Conv/DW_2D - Kernels/Integer/Conv/Regular_2D - - Kernels/Integer/GEMM/Regular - - Kernels/Integer/MatMul/Add - Kernels/Integer/MatMul/Regular - - Kernels/Integer/MaxPool - - Kernels/Integer/Pad/Regular_1D - Kernels/Integer/Pad/Regular_2D - - Kernels/Integer/ReduceMean - Kernels/Integer/ReduceSum - Kernels/Integer/Slice - - Models/TinyViT/5M/Layers/FP32/ReduceMean - - Kernels/Mixed/Dequant - Kernels/Mixed/Quant - Models/Transformer_DeepQuant - Kernels/Integer/Conv/DW_2D_RQ - Kernels/Integer/Conv/Regular_2D_RQ - Kernels/Integer/MatMul/Regular_RQ + pytest-marker: "kernels" generic-models: needs: select-env @@ -125,21 +43,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Models/Autoencoder1D - - Models/CCT/FP32/CCT_1_16_16_8 - Models/CCT/FP32/CCT_2_32_32_128_Opset20 - Models/CCT/Int/ICCT - Models/CCT/Int/ICCT_8 - Models/CCT/Int/ICCT_ITA - Models/CCT/Int/ICCT_ITA_8 - - Models/miniMobileNet - Models/miniMobileNetv2 - - Models/CNN_Linear1 - Models/TinyViT/Demo - Models/WaveFormer - - Models/CNN_Linear2 + pytest-marker: "models" diff --git a/.github/workflows/ci-platform-mempool.yml b/.github/workflows/ci-platform-mempool.yml index 04c65c215a..efda508257 100644 --- a/.github/workflows/ci-platform-mempool.yml +++ b/.github/workflows/ci-platform-mempool.yml @@ -35,35 +35,7 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/Integer/Add/MultIO - Kernels/Integer/Add/Regular - - Kernels/Integer/Conv/DW_1D - Kernels/Integer/Conv/Regular_1D - - Kernels/Integer/Conv/DW_2D - Kernels/Integer/Conv/Regular_2D - - Kernels/Integer/GEMM/Regular - - Kernels/Integer/MatMul/Add - Kernels/Integer/MatMul/Regular - - Kernels/Integer/MaxPool - - Kernels/Integer/Pad/Regular_1D - Kernels/Integer/Pad/Regular_2D - - Kernels/Integer/ReduceMean - Kernels/Integer/ReduceSum - - Kernels/Integer/Slice - - Kernels/Integer/Conv/Regular_2D_RQ - Kernels/Integer/Conv/DW_2D_RQ - Kernels/Integer/GEMM/Regular_RQPerRow - Kernels/Integer/MatMul/Regular_RQ + pytest-marker: "kernels" mempool-models: needs: select-env @@ -71,14 +43,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Models/CCT/Int/ICCT - Models/CCT/Int/ICCT_8 - Models/CCT/Int/ICCT_ITA - - Models/miniMobileNet - Models/miniMobileNetv2 - - Models/CNN_Linear1 - - Models/CNN_Linear2 + pytest-marker: "models" diff --git a/.github/workflows/ci-platform-siracusa-neureka-tiled.yml b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml index 9a3b31bf70..e76ee648c0 100644 --- a/.github/workflows/ci-platform-siracusa-neureka-tiled.yml +++ b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml @@ -31,116 +31,48 @@ jobs: siracusa-neureka-kernels-tiled-singlebuffer-L2: needs: select-env - uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/Integer/GEMM/Regular_RQPerColumn","L1":[16000]}, - {"name":"Kernels/Integer/Conv/PW_2D","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ","L1":[32000]} - ] - num-cores: 8 + pytest-marker: "kernels and singlebuffer and l2 and not wmem" siracusa-neureka-kernels-tiled-doublebuffer-L2: needs: select-env - uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/Integer/GEMM/Regular_RQPerColumn","L1":[16000]}, - {"name":"Kernels/Integer/Conv/PW_2D","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ","L1":[32000]} - ] - num-cores: 8 - # double buffer enabled: - double-buffer: true + pytest-marker: "kernels and doublebuffer and l2 and not wmem" siracusa-neureka-models-tiled-singlebuffer-L3: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - { name: "Models/miniMobileNet", L1: [2000] } # LMACAN: 1000 leads to non-2d transfers in L3! - - { name: "Kernels/Integer/Attention", L1: [2500] } - - { name: "Models/Transformer", L1: [15000] } - - { name: "Models/microLlama/microLlama1", L1: [10000] } - num-cores: [8] - default-memory-level: ["L3"] uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - default-memory-level: ${{ matrix.default-memory-level }} + pytest-marker: "models and singlebuffer and l3 and not wmem" siracusa-neureka-models-tiled-doublebuffer-L3: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - { name: "Models/miniMobileNet", L1: [2000] } # LMACAN note - - { name: "Kernels/Integer/Attention", L1: [5000] } - - { name: "Models/Transformer", L1: [30000] } - num-cores: [8] - double-buffer: [true] - default-memory-level: ["L3"] uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - double-buffer: ${{ matrix.double-buffer }} - default-memory-level: ${{ matrix.default-memory-level }} + pytest-marker: "models and doublebuffer and l3 and not wmem" siracusa-neureka-kernels-tiled-singlebuffer-L2-wmem: needs: select-env - uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/Integer/GEMM/Regular_RQPerColumn","L1":[16000]}, - {"name":"Kernels/Integer/Conv/PW_2D","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ","L1":[32000]}, - {"name":"Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ","L1":[32000]} - ] - num-cores: 8 - neureka-wmem: true + pytest-marker: "kernels and singlebuffer and l2 and wmem" siracusa-neureka-models-tiled-doublebuffer-L3-wmem: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - { name: "Models/miniMobileNet", L1: [2000] } # LMACAN note - - { name: "Kernels/Integer/Attention", L1: [3500] } - # - { name: "Models/Transformer", L1: [30000] } - - { name: "Models/microLlama/microLlama1", L1: [10000] } - num-cores: [8] - double-buffer: [true] - default-memory-level: ["L3"] - neureka-wmem: [true] uses: ./.github/workflows/_runner-siracusa-neureka-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - double-buffer: ${{ matrix.double-buffer }} - default-memory-level: ${{ matrix.default-memory-level }} - neureka-wmem: ${{ matrix.neureka-wmem }} + pytest-marker: "models and doublebuffer and l3 and wmem" diff --git a/.github/workflows/ci-platform-siracusa-tiled.yml b/.github/workflows/ci-platform-siracusa-tiled.yml index 0fd62294ac..6597f3e625 100644 --- a/.github/workflows/ci-platform-siracusa-tiled.yml +++ b/.github/workflows/ci-platform-siracusa-tiled.yml @@ -29,266 +29,56 @@ jobs: with: docker_image_deeploy: ${{ inputs.docker_image_deeploy }} - siracusa-kernels-tiled-singlebuffer-L2: + # Kernel tests - L2 singlebuffer + siracusa-kernels-tiled-l2-singlebuffer: needs: select-env - uses: ./.github/workflows/_runner-siracusa-tiled-sequential.yml + uses: ./.github/workflows/_runner-siracusa-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/FP32/ReLU","L1":[2000]}, - {"name":"Kernels/FP32/Softmax/Regular","L1":[4000]}, - - {"name":"Kernels/FP32/Add/Large","L1":[220000]}, - - {"name":"Kernels/FP32/Conv/DW_2D_Bias","L1":[7200]}, - {"name":"Kernels/FP32/Conv/DW_2D_NoBias","L1":[7200]}, - {"name":"Kernels/FP32/Conv/DW_2D_ZeroValuedBias","L1":[7200]}, - {"name":"Kernels/FP32/Conv/Regular_2D_Bias","L1":[6600]}, - {"name":"Kernels/FP32/Conv/Regular_2D_NoBias","L1":[1600]}, - {"name":"Kernels/FP32/Conv/Regular_2D_ZeroValuedBias","L1":[6600]}, - - {"name":"Kernels/FP32/GEMM/Regular","L1":[8000]}, - {"name":"Kernels/FP32/MatMul","L1":[2000]}, - {"name":"Kernels/FP32/MaxPool","L1":[2000]}, - {"name":"Kernels/FP32/Mul","L1":[2000]}, - {"name":"Kernels/FP32/LayerNorm","L1":[2000]}, - - {"name":"Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/AllAxes","L1":[50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3","L1":[50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes1_3","L1":[5000,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes2_1","L1":[6200,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axis0","L1":[8400,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axis2","L1":[8400,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add","L1":[8000]}, - - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/AllAxes","L1":[50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3","L1":[50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3","L1":[5000,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1","L1":[6200,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axis0","L1":[8400,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axis2","L1":[8400,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add","L1":[8000]}, - - {"name":"Kernels/FP32/Reshape/SkipConnection","L1":[1400]}, - {"name":"Kernels/FP32/Transpose","L1":[2000]}, - - {"name":"Kernels/Integer/Hardswish/Regular","L1":[750]}, - {"name":"Kernels/Integer/Softmax/Regular","L1":[800,500,300]}, - - {"name":"Kernels/Integer/Concat","L1":[32000,16000,8000]}, - - {"name":"Kernels/Integer/MatMul/Batch","L1":[20000]}, - {"name":"Kernels/Integer/MatMul/Regular","L1":[64000,32000,16000]}, + pytest-marker: "kernels and l2 and singlebuffer" - {"name":"Kernels/Integer/RMSNorm","L1":[2048,1024,512]}, - - {"name":"Kernels/Integer/Conv/Regular_2D_RQ","L1":[8000,6000,4000]}, - {"name":"Kernels/Integer/Conv/DW_2D_RQ","L1":[2561]}, - {"name":"Kernels/Integer/Conv/StriddedPadded_2D_RQ","L1":[600]}, - {"name":"Kernels/Integer/GEMM/Batch_RQ","L1":[20000]}, - {"name":"Kernels/Integer/Hardswish/Regular_RQ","L1":[750]} - ] - num-cores: 8 - - siracusa-kernels-tiled-doublebuffer-L2: + # Kernel tests - L2 doublebuffer + siracusa-kernels-tiled-l2-doublebuffer: needs: select-env - uses: ./.github/workflows/_runner-siracusa-tiled-sequential.yml + uses: ./.github/workflows/_runner-siracusa-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/FP32/ReLU","L1":[20]}, - {"name":"Kernels/FP32/Softmax/Regular","L1":[8000]}, - - {"name":"Kernels/FP32/Conv/DW_2D_Bias","L1":[10000]}, - {"name":"Kernels/FP32/Conv/DW_2D_NoBias","L1":[9800]}, - {"name":"Kernels/FP32/Conv/DW_2D_ZeroValuedBias","L1":[9800]}, - {"name":"Kernels/FP32/Conv/Regular_2D_Bias","L1":[8800]}, - {"name":"Kernels/FP32/Conv/Regular_2D_NoBias","L1":[2000]}, - {"name":"Kernels/FP32/Conv/Regular_2D_ZeroValuedBias","L1":[8800]}, - - {"name":"Kernels/FP32/GEMM/Regular","L1":[8000]}, - {"name":"Kernels/FP32/MatMul","L1":[5000]}, - {"name":"Kernels/FP32/MaxPool","L1":[5000]}, - {"name":"Kernels/FP32/Mul","L1":[2000]}, - {"name":"Kernels/FP32/LayerNorm","L1":[2000]}, - - {"name":"Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/AllAxes","L1":[100000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3","L1":[100000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes1_3","L1":[10000,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axes2_1","L1":[13000,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axis0","L1":[17000,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/Axis2","L1":[17000,50000]}, - {"name":"Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add","L1":[8000]}, - - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add","L1":[8000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/AllAxes","L1":[100000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3","L1":[100000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3","L1":[10000,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1","L1":[13000,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axis0","L1":[17000,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/Axis2","L1":[17000,50000]}, - {"name":"Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add","L1":[8000]}, - - {"name":"Kernels/FP32/Reshape/SkipConnection","L1":[2600]}, - {"name":"Kernels/FP32/Transpose","L1":[2000]}, - - {"name":"Kernels/Integer/Hardswish/Regular","L1":[750]}, - {"name":"Kernels/Integer/Softmax/Regular","L1":[1600,1000,600]}, - - {"name":"Kernels/Integer/Concat","L1":[64000,32000,16000]}, - {"name":"Kernels/Integer/MatMul/Regular","L1":[64000,32000,16000]}, - {"name":"Kernels/Integer/RMSNorm","L1":[4096,2048,1024]}, + pytest-marker: "kernels and l2 and doublebuffer" - {"name":"Kernels/Integer/Conv/Regular_2D_RQ","L1":[8000,6000,5000]}, - {"name":"Kernels/Integer/Conv/DW_2D_RQ","L1":[5121]}, - {"name":"Kernels/Integer/Hardswish/Regular_RQ","L1":[800]} - ] - num-cores: 8 - double-buffer: true - - siracusa-models-tiled-singlebuffer-L2: + # Model tests - L2 singlebuffer + siracusa-models-tiled-l2-singlebuffer: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - name: "Kernels/Integer/Attention" - L1: [60000, 10000, 5000] - - - name: "Models/CCT/FP32/CCT_1_16_16_8" - L1: [64000] - - - name: "Models/microLlama/microLlama1" - L1: [60000, 10000, 5000] - - name: "Models/microLlama/microLlama8" - L1: [60000, 10000, 5000] - - name: "Models/microLlama/microLlama8_parallel" - L1: [60000, 10000, 5000] - - - name: "Models/miniMobileNet" - L1: [60000, 12000, 6000, 3000] - - name: "Models/miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - - name: "Models/MLPerf/AnomalyDetection" - L1: [64000] - - name: "Models/MLPerf/ImageClassification" - L1: [64000] - - name: "Models/MLPerf/KeywordSpotting" - L1: [64000] - - - name: "Models/TinyViT/5M/Layers/FP32/ReduceMean" - L1: [200, 40000] - - name: "Models/TinyViT/Demo" - L1: [4000] - - - name: "Models/CNN_Linear2" - L1: [45000, 30000, 15000] - num-cores: [8] uses: ./.github/workflows/_runner-siracusa-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} + pytest-marker: "models and l2 and singlebuffer" - siracusa-models-tiled-singlebuffer-L3: + # Model tests - L2 doublebuffer + siracusa-models-tiled-l2-doublebuffer: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - name: "Kernels/Integer/Attention" - L1: [60000, 10000, 5000, 2500] - - - name: "Models/CCT/FP32/CCT_2_32_32_128" - L1: [128000] - - - name: "Models/microLlama/microLlama1" - L1: [60000, 10000, 5000] - - - name: "Models/miniMobileNet" - L1: [60000, 12000, 6000] # SCHEREMO note - - name: "Models/miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - name: "Models/TinyViT/5M/Layers/FP32/ReduceMean" - L1: [200, 40000] - - name: "Models/TinyViT/Demo" - L1: [4000] - - - name: "Models/CNN_Linear2" - L1: [45000, 30000, 16000] # SCHEREMO note - - name: "Models/CCT_Train/CCT2_FT2" - L1: [128000] - - name: "Models/Transformer" - L1: [60000, 30000, 15000] - num-cores: [8] - default-memory-level: ["L3"] uses: ./.github/workflows/_runner-siracusa-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - default-memory-level: ${{ matrix.default-memory-level }} + pytest-marker: "models and l2 and doublebuffer" - siracusa-models-tiled-doublebuffer-L3: + # Model tests - L3 singlebuffer + siracusa-models-tiled-l3-singlebuffer: needs: select-env - strategy: - fail-fast: false - matrix: - test-data: - - name: "Kernels/Integer/Attention" - L1: [60000, 20000, 10000, 5000] - - - name: "Models/CCT/FP32/CCT_2_32_32_128" - L1: [128000] - - - name: "Models/microLlama/microLlama1" - L1: [60000, 20000, 10000] - - name: "Models/microLlama/microLlama8" - L1: [60000, 20000, 10000] - - name: "Models/microLlama/microLlama8_parallel" - L1: [60000, 20000, 10000] - - - name: "Models/miniMobileNet" - L1: [60000, 24000, 12000, 6000] - - name: "Models/miniMobileNetv2" - L1: [60000, 32000, 24000, 16000] - - - name: "Models/TinyViT/5M/Layers/FP32/ReduceMean" - L1: [200, 40000] - - name: "Models/TinyViT/Demo" - L1: [4000] + uses: ./.github/workflows/_runner-siracusa-tiled.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + pytest-marker: "models and l3 and singlebuffer" - - name: "Models/CNN_Linear2" - L1: [60000, 45000, 30000] - - name: "Models/CCT_Train/CCT2_FT2" - L1: [128000] - - name: "Models/Transformer" - L1: [60000, 30000, 15000] - num-cores: [8] - double-buffer: [true] - default-memory-level: ["L3"] + # Model tests - L3 doublebuffer + siracusa-models-tiled-l3-doublebuffer: + needs: select-env uses: ./.github/workflows/_runner-siracusa-tiled.yml with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - double-buffer: ${{ matrix.double-buffer }} - default-memory-level: ${{ matrix.default-memory-level }} + pytest-marker: "models and l3 and doublebuffer" diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml index 5d863959fe..9cec1ef896 100644 --- a/.github/workflows/ci-platform-siracusa.yml +++ b/.github/workflows/ci-platform-siracusa.yml @@ -35,81 +35,7 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/FP32/ReLU - - Kernels/FP32/Softmax/CrossEntropy - Kernels/FP32/Softmax/CrossEntropyGrad - Kernels/FP32/Softmax/Grad - Kernels/FP32/Softmax/Regular - - Kernels/FP32/Add/Regular - - Kernels/FP32/Conv/DW_2D_Bias - Kernels/FP32/Conv/DW_2D_NoBias - Kernels/FP32/Conv/DW_2D_ZeroValuedBias - Kernels/FP32/Conv/Regular_2D_Bias - Kernels/FP32/Conv/Regular_2D_NoBias - Kernels/FP32/Conv/Regular_2D_ZeroValuedBias - - Kernels/FP32/GEMM/Regular - Kernels/FP32/MatMul - Kernels/FP32/MaxPool - Kernels/FP32/Mul - Kernels/FP32/LayerNorm - - Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean - Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add - Kernels/FP32/ReduceMean/KeepDims/AllAxes - Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3 - Kernels/FP32/ReduceMean/KeepDims/Axes1_3 - Kernels/FP32/ReduceMean/KeepDims/Axes2_1 - Kernels/FP32/ReduceMean/KeepDims/Axis0 - Kernels/FP32/ReduceMean/KeepDims/Axis2 - Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add - - Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean - Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add - Kernels/FP32/ReduceMean/NoKeepDims/AllAxes - Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3 - Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3 - Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1 - Kernels/FP32/ReduceMean/NoKeepDims/Axis0 - Kernels/FP32/ReduceMean/NoKeepDims/Axis2 - Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add - - Kernels/FP32/ReduceSum - Kernels/FP32/Reshape/SkipConnection - - Kernels/FP32/Transpose - - Kernels/Integer/Hardswish/Regular - Kernels/Integer/Softmax/Regular - - Kernels/Integer/Add/MultIO - Kernels/Integer/Add/Regular - - Kernels/Integer/Concat - - Kernels/Integer/MatMul/Add - Kernels/Integer/MatMul/Regular - - Kernels/Integer/Pad/Regular_1D - Kernels/Integer/Pad/Regular_2D - - Kernels/Integer/RMSNorm - - Models/TinyViT/5M/Layers/FP32/ReduceMean - - Others/Backtracking - Kernels/Mixed/Dequant - Kernels/Mixed/Quant - Models/Transformer_DeepQuant - Kernels/Integer/Conv/Regular_2D_RQ - Kernels/Integer/Conv/DW_2D_RQ - Kernels/Integer/Hardswish/Regular_RQ - Kernels/Integer/TrueIntegerDiv - num-cores: 8 + test-type: kernels siracusa-models: needs: select-env @@ -117,20 +43,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/Integer/Attention - - Models/CCT/FP32/CCT_1_16_16_8 - Models/CCT/FP32/CCT_2_32_32_128_Opset20 - - Models/miniMobileNet - Models/miniMobileNetv2 - - Models/MLPerf/KeywordSpotting - Models/MLPerf/ImageClassification - Models/MLPerf/AnomalyDetection - - Models/TinyViT/Demo - - Models/CNN_Linear2 - num-cores: 8 + test-type: models diff --git a/.github/workflows/ci-platform-snitch-tiled.yml b/.github/workflows/ci-platform-snitch-tiled.yml index 3850ce2bde..5390d8ad16 100644 --- a/.github/workflows/ci-platform-snitch-tiled.yml +++ b/.github/workflows/ci-platform-snitch-tiled.yml @@ -35,19 +35,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - tests-config: | - [ - {"name":"Kernels/Integer/Add/Large","L1":[5000,10000]}, - {"name":"Kernels/Integer/Softmax/Large","L1":[5000,10000]}, - - {"name":"Kernels/FP32/Softmax/Regular","L1":[2000,5000,10000]}, - - {"name":"Kernels/FP32/GEMM/Regular","L1":[2000,5000,10000]}, - {"name":"Kernels/FP32/GEMM/TransB","L1":[2000,5000,10000]}, - - {"name":"Kernels/Integer/iNoNorm","L1":[5000,10000]}, - {"name":"Kernels/Integer/Add/Regular_RQ","L1":[5000,10000]}, - {"name":"Kernels/Integer/GEMM/Regular_RQPerRow","L1":[2000,5000]} - ] - simulators: | - gvsoc + pytest-marker: "kernels and singlebuffer and l2" diff --git a/.github/workflows/ci-platform-snitch.yml b/.github/workflows/ci-platform-snitch.yml index 21f436b2a6..c1ae694148 100644 --- a/.github/workflows/ci-platform-snitch.yml +++ b/.github/workflows/ci-platform-snitch.yml @@ -35,21 +35,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/FP32/Softmax/Regular - - Kernels/Integer/Add/Large - Kernels/Integer/Add/Regular - - Kernels/Integer/Softmax/Large - Kernels/Integer/Softmax/Regular - - Kernels/Integer/MatMul/Regular - - Kernels/Integer/iNoNorm - Kernels/Integer/GEMM/Regular_RQPerRow - Kernels/Integer/Add/Regular_RQ - Kernels/Integer/GEMM/TransB_RQ - num-cores: 9 - simulators: | - gvsoc + pytest-marker: "kernels" diff --git a/.github/workflows/ci-platform-softhier.yml b/.github/workflows/ci-platform-softhier.yml index 1409743db0..28a85160be 100644 --- a/.github/workflows/ci-platform-softhier.yml +++ b/.github/workflows/ci-platform-softhier.yml @@ -35,5 +35,4 @@ jobs: with: runner: ${{ needs.select-env.outputs.runner }} docker-image: ${{ needs.select-env.outputs.image }} - test-names: | - Kernels/Integer/Add/Regular + pytest-marker: "kernels" diff --git a/.github/workflows/infra-generate-ccache.yml b/.github/workflows/infra-generate-ccache.yml index f04f1d63f6..e4d00ea911 100644 --- a/.github/workflows/infra-generate-ccache.yml +++ b/.github/workflows/infra-generate-ccache.yml @@ -29,20 +29,22 @@ jobs: - name: Build Deeploy shell: bash run: pip install -e . + - name: Generate CCache run: | cd DeeployTest mkdir -p /app/.ccache export CCACHE_DIR=/app/.ccache - python testRunner_generic.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_mempool.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_cortexm.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_snitch.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_tiled_snitch.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_siracusa.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_tiled_siracusa.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/Kernels/Integer/Add/Regular - python testRunner_chimera.py -t ./Tests/Kernels/Integer/Add/Regular + pytest 'test_platforms.py::test_generic_kernels[Kernels/Integer/Add/Regular]' --skipsim + pytest 'test_platforms.py::test_mempool_kernels[Kernels/Integer/Add/Regular]' --skipsim + pytest 'test_platforms.py::test_cortexm_kernels[Kernels/Integer/Add/Regular]' --skipsim + pytest 'test_platforms.py::test_snitch_kernels[Kernels/Integer/Add/Regular]' --skipsim + pytest 'test_platforms.py::test_snitch_tiled_kernels_l2_singlebuffer[Kernels/Integer/Add/Large-5000-L2-singlebuffer]' --skipsim + pytest 'test_platforms.py::test_siracusa_kernels[Kernels/Integer/Add/Regular]' --skipsim + pytest 'test_platforms.py::test_siracusa_tiled_kernels_l2_singlebuffer[Kernels/Integer/MatMul/Regular-64000-L2-singlebuffer]' --skipsim + pytest 'test_platforms.py::test_siracusa_neureka_tiled_kernels_l2_singlebuffer[Kernels/Integer/GEMM/Regular_RQPerColumn-16000-L2-singlebuffer]' --skipsim + pytest 'test_platforms.py::test_chimera_kernels[Kernels/Integer/Add/Regular]' --skipsim + - name: Clean and Upload CCache uses: actions/cache@v4 with: diff --git a/Container/Dockerfile.deeploy b/Container/Dockerfile.deeploy index 68f64748cc..65265a6eeb 100644 --- a/Container/Dockerfile.deeploy +++ b/Container/Dockerfile.deeploy @@ -86,6 +86,9 @@ WORKDIR /app COPY pyproject.toml ./ +# Add nvidia channel to the pip configuration +RUN mkdir -p /etc && printf "[global]\nextra-index-url = https://pypi.ngc.nvidia.com\n" > /etc/pip.conf + # Install dependencies RUN mkdir -p /root/.cargo/bin/ && \ apt-get update && \ @@ -103,7 +106,6 @@ RUN mkdir -p /root/.cargo/bin/ && \ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \ python get-pip.py && \ rm get-pip.py && \ - pip install nvidia-pyindex && \ pip install toml-to-requirements && \ toml-to-req --toml-file pyproject.toml && \ pip install -r requirements.txt diff --git a/Deeploy/TilingExtension/TilerExtension.py b/Deeploy/TilingExtension/TilerExtension.py index 27ca222e4e..9b48d9456c 100644 --- a/Deeploy/TilingExtension/TilerExtension.py +++ b/Deeploy/TilingExtension/TilerExtension.py @@ -52,7 +52,7 @@ class Tiler(): _MINIMALLOC_OUTPUT_FILENAME = "output_minimalloc" # Initialize with the list of TemplateTCFbinding - def __init__(self, memoryHierarchy: MemoryHierarchy): + def __init__(self, memoryHierarchy: MemoryHierarchy, testName: Optional[str] = None, workDir: Optional[str] = None): self.memoryHierarchy = memoryHierarchy self.tilerModel: Optional[TilerModel] = None @@ -66,6 +66,23 @@ def __init__(self, memoryHierarchy: MemoryHierarchy): self.memoryAllocStrategy: Literal["TetrisRandom", "TetrisCo-Opt", "MiniMalloc"] = "TetrisRandom" self.searchStrategy: Literal["min", "max", "random-max"] = "random-max" + if workDir is not None: + os.makedirs(workDir, exist_ok = True) + minimalloc_base = os.path.join(workDir, self._MINIMALLOC_INPUT_FILENAME) + minimalloc_output_base = os.path.join(workDir, self._MINIMALLOC_OUTPUT_FILENAME) + else: + minimalloc_base = self._MINIMALLOC_INPUT_FILENAME + minimalloc_output_base = self._MINIMALLOC_OUTPUT_FILENAME + + if testName is not None: + # VJUNG: Sanitize path + safe_test_name = testName.replace("/", "_").replace("\\", "_") + self._minimalloc_input = f"{minimalloc_base}_{safe_test_name}" + self._minimalloc_output = f"{minimalloc_output_base}_{safe_test_name}" + else: + self._minimalloc_input = minimalloc_base + self._minimalloc_output = minimalloc_output_base + @property def worstCaseBufferSize(self): return self._worstCaseBufferSize @@ -238,7 +255,7 @@ def _convertCtxtToStaticSchedule(self, ctxt: NetworkContext, def minimalloc(self, memoryMap, ctxt, nodeMemoryConstraint, capacity: int, memoryLevel: str): - with open(f"{self._MINIMALLOC_INPUT_FILENAME}.csv", mode = "w", newline = "") as file: + with open(f"{self._minimalloc_input}.csv", mode = "w", newline = "") as file: writer = csv.writer(file, lineterminator = "\n") writer.writerow(["id", "lower", "upper", "size"]) for memoryBlock in memoryMap: @@ -272,8 +289,8 @@ def minimalloc(self, memoryMap, ctxt, nodeMemoryConstraint, capacity: int, memor raise KeyError("MINIMALLOC_INSTALL_DIR symbol not found!") minimallocOutput = subprocess.run([ - f"{minimallocInstallDir}/minimalloc", f"--capacity={capacity}", - f"--input={self._MINIMALLOC_INPUT_FILENAME}.csv", f"--output={self._MINIMALLOC_OUTPUT_FILENAME}.csv" + f"{minimallocInstallDir}/minimalloc", f"--capacity={capacity}", f"--input={self._minimalloc_input}.csv", + f"--output={self._minimalloc_output}.csv" ], capture_output = True, text = True) @@ -284,7 +301,7 @@ def minimalloc(self, memoryMap, ctxt, nodeMemoryConstraint, capacity: int, memor ) raise subprocess.CalledProcessError(minimallocOutput.returncode, " ".join(minimallocOutput.args)) - with open(f"{self._MINIMALLOC_OUTPUT_FILENAME}.csv", mode = "r", newline = "") as file: + with open(f"{self._minimalloc_output}.csv", mode = "r", newline = "") as file: reader = csv.reader(file) header = next(reader) for row in reader: @@ -944,11 +961,15 @@ def testMemoryMapCorrectness(self, memoryMap: Dict[str, List[List[MemoryBlock]]] class TilerDeployerWrapper(NetworkDeployerWrapper): - def __init__(self, deployer: Union[MemoryLevelAwareDeployer, MemoryDeployerWrapper], tilerCls: Type[Tiler] = Tiler): + def __init__(self, + deployer: Union[MemoryLevelAwareDeployer, MemoryDeployerWrapper], + tilerCls: Type[Tiler] = Tiler, + testName: Optional[str] = None, + workDir: Optional[str] = None): super().__init__(deployer) assert isinstance(self.Platform, (MemoryPlatform, MemoryPlatformWrapper)), \ f"Platform should be a MemoryPlatform or MemoryPlatformWrapper! Got {type(self.Platform).__name__}" - self.tiler = tilerCls(self.Platform.memoryHierarchy) + self.tiler = tilerCls(self.Platform.memoryHierarchy, testName = testName, workDir = workDir) @property def worstCaseBufferSize(self): diff --git a/DeeployTest/README.md b/DeeployTest/README.md new file mode 100644 index 0000000000..b5db1988b0 --- /dev/null +++ b/DeeployTest/README.md @@ -0,0 +1,62 @@ + + +# How to use the DeeployTest PyTest Suite? + +### Executing and Collecting Test Groups + +The test suite is located in the `DeeployTest` folder, all commands below are assumed to be executed from the `DeeployTest` folder. The test suite is grouped with different markers, you can list the markers with `pytest --markers`. This will return something like: +``` +@pytest.mark.generic: mark test as a Generic platform test +@pytest.mark.cortexm: mark test as a Cortex-M (QEMU-ARM) platform test +@pytest.mark.mempool: mark test as a MemPool platform test +``` + +You can run all test from a given mark group with `pytest -m -v`. Each platform has a given marker, if you want to run all tests from the generic platform, you can use `pytest -m generic -v`. + +You can use boolean expressions on the markers to execute unions or intersections of markers. For instance, to execute only the kernel tests from the generic platform, one can use `pytest -m 'generic and kernels' -v`. + +To display the tests captured by a given marker or expression, you can use the `--collect-only` flag. For instance, to list the kernel tests on the Siracusa with Neureka platform that are from L2 and single-buffered, I can use `pytest -m 'siracusa_neureka_tiled and kernels and l2 and singlebuffer' -v --collect-only`, which returns: + +``` +platform linux -- Python 3.10.0, pytest-9.0.2, pluggy-1.6.0 -- /usr/scratch/normandie/jungvi/micromamba/envs/deeploy/bin/python3.10 +cachedir: .pytest_cache +rootdir: /scratch/jungvi/Deeploy/DeeployTest +configfile: pytest.ini +plugins: xdist-3.8.0 +collected 378 items / 370 deselected / 8 selected + + + + + + + + + + + +``` + +### Executing a Single Test + +To run a single test, one can use the test identifier from the `--collect-only` output, for instance `pytest 'test_platforms.py::test_siracusa_neureka_tiled_kernels_l2_singlebuffer[testRequantizedLinear-16000-L2-singlebuffer]' -v`. + +### Controlling Test Verbosity + +By default, the test output is captured and displayed only if a test fails. If you want to see the captured output, use the `-s` flag. To increase the verbosity of the test, you can add more `v` to the `-v` flag, for instance, `-vvv` will display the commands executed during the test. You can filter the level of the messages from Python's built-in logging module with `--log-cli-level=`. For instance, the following line captures only the commands executed by the tests: +``` +pytest test_platforms.py -m "generic and kernels" -vvv --log-cli-level=DEBUG +``` + +### Parallelized Test Execution + +You can run tests in parallel with the `-n` flag followed by the number of parallel threads. For instance, to run all generic tests with 16 threads, you can use: +``` +pytest test_platforms.py -m generic -v -n 16 +``` + +### Misc + +- When running `pytest -m ` in a folder, PyTest will scan each file looking for tests. To speed up the detection you can specify the platform test file like `pytest test_platforms.py -m `. +- If you place a breakpoint like `import IPython; IPython.embed()`, you need to run the test with `-s` to be able to enter breakpoints. +- The `--pdb` flag is very useful as it drops a debugger session on failure. \ No newline at end of file diff --git a/DeeployTest/conftest.py b/DeeployTest/conftest.py new file mode 100644 index 0000000000..8c4847a296 --- /dev/null +++ b/DeeployTest/conftest.py @@ -0,0 +1,143 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +import os +from pathlib import Path + +import coloredlogs +import pytest + +from Deeploy.Logging import DEFAULT_FMT +from Deeploy.Logging import DEFAULT_LOGGER as log + + +def pytest_addoption(parser: pytest.Parser) -> None: + """Native PyTest hook: add custom command-line options for Deeploy tests.""" + parser.addoption( + "--skipgen", + action = "store_true", + default = False, + help = "Skip network generation step", + ) + parser.addoption( + "--skipsim", + action = "store_true", + default = False, + help = "Skip simulation step (only generate and build)", + ) + parser.addoption( + "--toolchain", + action = "store", + default = "LLVM", + help = "Compiler toolchain to use (LLVM or GCC)", + ) + parser.addoption( + "--toolchain-install-dir", + action = "store", + default = os.environ.get("LLVM_INSTALL_DIR"), + help = "Path to toolchain installation directory", + ) + parser.addoption( + "--cmake-args", + action = "append", + default = [], + help = "Additional CMake arguments (can be used multiple times)", + ) + + +def pytest_configure(config: pytest.Config) -> None: + """Native PyTest hook: configure pytest for Deeploy tests.""" + # Register custom markers + config.addinivalue_line("markers", "generic: mark test as a Generic platform test") + config.addinivalue_line("markers", "cortexm: mark test as a Cortex-M (QEMU-ARM) platform test") + config.addinivalue_line("markers", "mempool: mark test as a MemPool platform test") + config.addinivalue_line("markers", "chimera: mark test as a Chimera platform test") + config.addinivalue_line("markers", "softhier: mark test as a SoftHier platform test") + config.addinivalue_line("markers", "snitch: mark test as a Snitch platform test") + config.addinivalue_line("markers", "snitch_tiled: mark test as a Snitch platform test (tiled)") + config.addinivalue_line("markers", "siracusa: mark test as a Siracusa platform test (untiled)") + config.addinivalue_line("markers", "siracusa_tiled: mark test as a Siracusa platform test (tiled)") + config.addinivalue_line("markers", + "siracusa_neureka_tiled: mark test as a Siracusa + Neureka platform test (tiled)") + config.addinivalue_line("markers", "kernels: mark test as a kernel test (individual operators)") + config.addinivalue_line("markers", "models: mark test as a model test (full networks)") + config.addinivalue_line("markers", "singlebuffer: mark test as single-buffer configuration") + config.addinivalue_line("markers", "doublebuffer: mark test as double-buffer configuration") + config.addinivalue_line("markers", "l2: mark test as L2 default memory level") + config.addinivalue_line("markers", "l3: mark test as L3 default memory level") + config.addinivalue_line("markers", "wmem: mark test as using Neureka weight memory") + config.addinivalue_line("markers", "dma: mark test as DMA test") + config.addinivalue_line( + "markers", + "deeploy_internal: mark test as internal Deeploy test (state serialization, extensions, transformations)") + + # Configure logging based on verbosity + verbosity = config.option.verbose + if verbosity >= 3: + coloredlogs.install(level = 'DEBUG', logger = log, fmt = DEFAULT_FMT) + elif verbosity >= 2: + coloredlogs.install(level = 'INFO', logger = log, fmt = DEFAULT_FMT) + else: + coloredlogs.install(level = 'WARNING', logger = log, fmt = DEFAULT_FMT) + + +@pytest.fixture(scope = "session") +def deeploy_test_dir(): + """Return the DeeployTest directory path.""" + return Path(__file__).parent + + +@pytest.fixture(scope = "session") +def tests_dir(deeploy_test_dir): + """Return the Tests directory path.""" + return deeploy_test_dir / "Tests" + + +@pytest.fixture(scope = "session") +def toolchain_dir(request): + """Return the toolchain installation directory.""" + toolchain_install = request.config.getoption("--toolchain-install-dir") + if toolchain_install is None: + pytest.skip(reason = "LLVM_INSTALL_DIR not set") + return toolchain_install + + +@pytest.fixture(scope = "session", autouse = True) +def ccache_dir(): + """Setup and return ccache directory.""" + # Use existing CCACHE_DIR if already set + if "CCACHE_DIR" in os.environ: + return Path(os.environ["CCACHE_DIR"]) + + # Fall back to /app/.ccache if it exists (for CI containers) + ccache_path = Path("/app/.ccache") + if ccache_path.exists(): + os.environ["CCACHE_DIR"] = str(ccache_path) + return ccache_path + + return None + + +@pytest.fixture +def skipgen(request): + """Return whether to skip network generation.""" + return request.config.getoption("--skipgen") + + +@pytest.fixture +def skipsim(request): + """Return whether to skip simulation.""" + return request.config.getoption("--skipsim") + + +@pytest.fixture +def toolchain(request): + """Return the toolchain to use.""" + return request.config.getoption("--toolchain") + + +@pytest.fixture +def cmake_args(request): + """Return additional CMake arguments.""" + return request.config.getoption("--cmake-args") diff --git a/DeeployTest/pytest.ini b/DeeployTest/pytest.ini new file mode 100644 index 0000000000..8ff98ae2dd --- /dev/null +++ b/DeeployTest/pytest.ini @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +[pytest] +# Pytest configuration for Deeploy tests + +# Test discovery patterns +python_files = test_*.py +python_classes = Test* +python_functions = test_* + +# Minimum version +minversion = 6.0 + +# Add current directory to Python path +pythonpath = . + +# Default options +addopts = + -ra + --strict-markers + --strict-config + --showlocals + +# Test output +console_output_style = progress + +# Logging +log_cli = false +log_cli_level = INFO +log_cli_format = %(levelname)s %(message)s + +# Warnings +filterwarnings = + error + ignore::DeprecationWarning + ignore::PendingDeprecationWarning diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index 4b1ebef20b..01216984af 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import argparse +import hashlib import os import sys from collections import OrderedDict @@ -115,14 +116,18 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg deployer = MemoryDeployerWrapper(deployer, memoryLevelAnnotationPasses) # Make the deployer tiler aware + # VJUNG: Create unique ID for the IO files of minimalloc and prevent conflict in case of parallel execution + unique_params = f"{args.dumpdir}_L1{args.l1}_L2{args.l2}_{args.defaultMemLevel}_DB{args.doublebuffer}" + testIdentifier = hashlib.md5(unique_params.encode()).hexdigest()[:16] + if args.doublebuffer: assert args.defaultMemLevel in ["L3", "L2"] if args.defaultMemLevel == "L3": - deployer = TilerDeployerWrapper(deployer, DBOnlyL3Tiler) + deployer = TilerDeployerWrapper(deployer, DBOnlyL3Tiler, testName = testIdentifier, workDir = args.dumpdir) else: - deployer = TilerDeployerWrapper(deployer, DBTiler) + deployer = TilerDeployerWrapper(deployer, DBTiler, testName = testIdentifier, workDir = args.dumpdir) else: - deployer = TilerDeployerWrapper(deployer, SBTiler) + deployer = TilerDeployerWrapper(deployer, SBTiler, testName = testIdentifier, workDir = args.dumpdir) deployer.tiler.visualizeMemoryAlloc = args.plotMemAlloc deployer.tiler.memoryAllocStrategy = args.memAllocStrategy diff --git a/DeeployTest/testRunner_chimera.py b/DeeployTest/testRunner_chimera.py deleted file mode 100644 index d3a7093a72..0000000000 --- a/DeeployTest/testRunner_chimera.py +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = False, - description = "Deeploy Code Generation Utility for the Chimera Platform (Host, no Tiling).") - - parser.add_argument('--simulator', - metavar = "", - dest = "simulator", - type = str, - choices = ["gvsoc"], - default = "gvsoc", - help = "Select the simulator to use") - - args = parser.parse_args() - - testRunner = TestRunner(platform = "Chimera", simulator = args.simulator, tiling = False, argument_parser = parser) - - testRunner.run() diff --git a/DeeployTest/testRunner_cortexm.py b/DeeployTest/testRunner_cortexm.py deleted file mode 100644 index 64d6246b74..0000000000 --- a/DeeployTest/testRunner_cortexm.py +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = False, - description = "Deeploy Code Generation Utility for the ARM (QEMU) Platform (no Tiling).") - args = parser.parse_args() - - testRunner = TestRunner(platform = "QEMU-ARM", simulator = "qemu", tiling = False, argument_parser = parser) - - testRunner.run() diff --git a/DeeployTest/testRunner_generic.py b/DeeployTest/testRunner_generic.py deleted file mode 100644 index 496b1db394..0000000000 --- a/DeeployTest/testRunner_generic.py +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = False, - description = "Deeploy Code Generation Utility for the Generic Platform (Host Machine, no Tiling).") - args = parser.parse_args() - - testRunner = TestRunner(platform = "Generic", simulator = "host", tiling = False, argument_parser = parser) - - testRunner.run() diff --git a/DeeployTest/testRunner_mempool.py b/DeeployTest/testRunner_mempool.py deleted file mode 100644 index 919603f454..0000000000 --- a/DeeployTest/testRunner_mempool.py +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - parser = TestRunnerArgumentParser( - tiling_arguments = False, description = "Deeploy Code Generation Utility for the MemPool Platform (no Tiling).") - - parser.add_argument('-n', - metavar = 'num_threads', - dest = 'num_threads', - type = int, - default = 16, - help = 'Number of parallel threads\n') - args = parser.parse_args() - - testRunner = TestRunner(platform = "MemPool", simulator = "banshee", tiling = False, argument_parser = parser) - - testRunner.cmake_args += f" -D num_threads={args.num_threads}" - - testRunner.run() diff --git a/DeeployTest/testRunner_siracusa.py b/DeeployTest/testRunner_siracusa.py deleted file mode 100644 index b83046de55..0000000000 --- a/DeeployTest/testRunner_siracusa.py +++ /dev/null @@ -1,31 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = False, - description = "Deeploy Code Generation Utility for the Siracusa Platform (no Tiling).") - - parser.add_argument('--cores', - metavar = '', - dest = 'cores', - type = int, - default = 8, - help = 'Set number of cluster cores') - - parser.add_argument('--profileUntiled', - action = 'store_true', - dest = 'profileUntiled', - default = False, - help = 'Profile Untiled') - - args = parser.parse_args() - - testRunner = TestRunner(platform = "Siracusa", simulator = "gvsoc", tiling = False, argument_parser = parser) - - testRunner.cmake_args += f" -D NUM_CORES={args.cores}" - testRunner.run() diff --git a/DeeployTest/testRunner_siracusa_l3dma.py b/DeeployTest/testRunner_siracusa_l3dma.py deleted file mode 100644 index b70d8dda22..0000000000 --- a/DeeployTest/testRunner_siracusa_l3dma.py +++ /dev/null @@ -1,98 +0,0 @@ -# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -import os - -import numpy as np -from testUtils.codeGenerate import generateTestNetwork -from testUtils.dmaUtils import MemcpyLayer, MemcpyParser, MemcpyTileConstraint, MemcpyTypeChecker, generate_graph, \ - memcpyTemplate, prepare_deployer_with_custom_tiling, setup_pulp_deployer -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser -from testUtils.typeMapping import baseTypeFromName, dtypeFromDeeployType - -from Deeploy.AbstractDataTypes import PointerClass -from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ - MemoryManagementGeneration -from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeMapper, _NoVerbosity -from Deeploy.Targets.PULPOpen.Bindings import L3MemoryAwareFunctionCallClosure, TilingCallClosure -from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3Tiling import PULPL3Tiling -from Deeploy.Targets.PULPOpen.DMA.L3Dma import l3DmaHack -from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ - TilingVariableReplacementUpdate -from Deeploy.TilingExtension.TilerExtension import TilingReadyNodeBindings - -testRunnerArgumentParser = TestRunnerArgumentParser(tiling_arguments = True) -testRunnerArgumentParser.add_argument('--input-shape', - nargs = '+', - required = True, - dest = 'input_shape', - type = int, - help = "Shape of the copied tensor") -testRunnerArgumentParser.add_argument('--tile-shape', - nargs = '+', - required = True, - dest = 'tile_shape', - type = int, - help = "Shape of the tiles produced in the manual tiling solution") -testRunnerArgumentParser.add_argument('--node-count', - dest = 'node_count', - type = int, - default = 1, - help = "Number of generated memcpy nodes") -testRunnerArgumentParser.add_argument('--type', type = str, default = "uint8_t", help = "Tensor elements datatype") -testRunner = TestRunner('Siracusa', 'gvsoc', True, testRunnerArgumentParser) - -inputShape = testRunner._args.input_shape -tileShape = testRunner._args.tile_shape -node_count = testRunner._args.node_count -_type = baseTypeFromName(testRunner._args.type) -dtype = dtypeFromDeeployType(_type) -defaultMemory = "L3" -targetMemory = "L2" - -assert len(inputShape) == len(tileShape), \ - f'Input and tile shape should be of the same dimensionality. Received {len(inputShape)}D input shape vs. {len(tileShape)}D tile shape.' -assert all(tileDim <= inDim for inDim, tileDim in zip(inputShape, tileShape)), \ - f'Each tile shape dimension should be smaller then the corresponding input one. Received {tileShape} > {inputShape}' - -graph = generate_graph(node_count, inputShape, dtype) -inputTypes = {"input_0": PointerClass(_type)} -_DEEPLOYSTATEDIR = os.path.join(testRunner._dir_gen, "deeployStates") -deployer = setup_pulp_deployer(defaultMemory, targetMemory, graph, inputTypes, testRunner._args.doublebuffer, - _DEEPLOYSTATEDIR) - -transformer = CodeTransformation([ - TilingVariableReplacement(targetMemory), - TilingCallClosure(writeback = False, generateStruct = True), - TilingVariableReplacementUpdate(targetMemory), - PULPL3Tiling("L3", "L2", l3DmaHack), - ArgumentStructGeneration(), - L3MemoryAwareFunctionCallClosure(writeback = False), - MemoryManagementGeneration("L2"), - MemoryManagementGeneration("L3.*"), - MemoryManagementGeneration(), -]) - -binding = NodeBinding(MemcpyTypeChecker(), memcpyTemplate, transformer) -tilingReadyBindings = TilingReadyNodeBindings([binding], MemcpyTileConstraint()) -memcpyMapper = NodeMapper(MemcpyParser(), tilingReadyBindings) -memcpyMapping = {"Memcpy": MemcpyLayer([memcpyMapper])} -deployer.Platform.engines[0].Mapping.update(memcpyMapping) - -prepare_deployer_with_custom_tiling(deployer, defaultMemory, targetMemory, tileShape, testRunner._args.doublebuffer) - -if not testRunner._args.skipgen: - if dtype == np.float32: - test_inputs = np.random.rand(*inputShape) - else: - info = np.iinfo(dtype) - test_inputs = np.arange(stop = np.prod(inputShape), dtype = dtype).reshape(inputShape) - test_outputs = test_inputs - generateTestNetwork(deployer, [test_inputs], [test_outputs], testRunner._dir_gen, _NoVerbosity) - -# Deconstructed testRunner.run() with skipped generation because we did the generation already -testRunner.configure_cmake_project() -testRunner.build_binary() -if not testRunner._args.skipsim: - testRunner.run_simulation() diff --git a/DeeployTest/testRunner_siracusa_mchandma.py b/DeeployTest/testRunner_siracusa_mchandma.py deleted file mode 100644 index 56ed6f5a14..0000000000 --- a/DeeployTest/testRunner_siracusa_mchandma.py +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -import os - -import numpy as np -from testUtils.codeGenerate import generateTestNetwork -from testUtils.dmaUtils import MemcpyLayer, MemcpyParser, MemcpyTileConstraint, MemcpyTypeChecker, generate_graph, \ - memcpyTemplate, prepare_deployer_with_custom_tiling, setup_pulp_deployer -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser -from testUtils.typeMapping import baseTypeFromName, dtypeFromDeeployType - -from Deeploy.AbstractDataTypes import PointerClass -from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ - MemoryManagementGeneration -from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeMapper, _NoVerbosity -from Deeploy.Targets.PULPOpen.Bindings import MemoryAwareFunctionCallClosure, TilingCallClosure -from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterTiling import PULPClusterTiling -from Deeploy.Targets.PULPOpen.DMA.MchanDma import MchanDma -from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ - TilingVariableReplacementUpdate -from Deeploy.TilingExtension.TilerExtension import TilingReadyNodeBindings - -testRunnerArgumentParser = TestRunnerArgumentParser(tiling_arguments = True) -testRunnerArgumentParser.add_argument('--input-shape', - nargs = '+', - required = True, - dest = 'input_shape', - type = int, - help = "Shape of the copied tensor") -testRunnerArgumentParser.add_argument('--tile-shape', - nargs = '+', - required = True, - dest = 'tile_shape', - type = int, - help = "Shape of the tiles produced in the manual tiling solution") -testRunnerArgumentParser.add_argument('--node-count', - dest = 'node_count', - type = int, - default = 1, - help = "Number of generated memcpy nodes") -testRunnerArgumentParser.add_argument('--type', type = str, default = "uint8_t", help = "Tensor elements datatype") -testRunner = TestRunner('Siracusa', 'gvsoc', True, testRunnerArgumentParser) - -inputShape = testRunner._args.input_shape -tileShape = testRunner._args.tile_shape -node_count = testRunner._args.node_count -_type = baseTypeFromName(testRunner._args.type) -dtype = dtypeFromDeeployType(_type) -defaultMemory = "L2" -targetMemory = "L1" - -assert len(inputShape) == len(tileShape), \ - f'Input and tile shape should be of the same dimensionality. Received {len(inputShape)}D input shape vs. {len(tileShape)}D tile shape.' -assert all(tileDim <= inDim for inDim, tileDim in zip(inputShape, tileShape)), \ - f'Each tile shape dimension should be smaller then the corresponding input one. Received {tileShape} > {inputShape}' - -graph = generate_graph(node_count, inputShape, dtype) -inputTypes = {"input_0": PointerClass(_type)} -_DEEPLOYSTATEDIR = os.path.join(testRunner._dir_gen, "deeployStates") -deployer = setup_pulp_deployer(defaultMemory, targetMemory, graph, inputTypes, testRunner._args.doublebuffer, - _DEEPLOYSTATEDIR) - -transformer = CodeTransformation([ - TilingVariableReplacement(targetMemory), - TilingCallClosure(writeback = False, generateStruct = True), - TilingVariableReplacementUpdate(targetMemory), - PULPClusterTiling(defaultMemory, targetMemory, MchanDma()), - ArgumentStructGeneration(), - MemoryManagementGeneration(targetMemory), - TilingVariableReplacement(defaultMemory), - MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), - MemoryManagementGeneration(defaultMemory), - MemoryManagementGeneration(), -]) - -binding = NodeBinding(MemcpyTypeChecker(), memcpyTemplate, transformer) -tilingReadyBindings = TilingReadyNodeBindings([binding], MemcpyTileConstraint()) -memcpyMapper = NodeMapper(MemcpyParser(), tilingReadyBindings) -memcpyMapping = {"Memcpy": MemcpyLayer([memcpyMapper])} -deployer.Platform.engines[0].Mapping.update(memcpyMapping) - -prepare_deployer_with_custom_tiling(deployer, defaultMemory, targetMemory, tileShape, testRunner._args.doublebuffer) - -if not testRunner._args.skipgen: - if dtype == np.float32: - test_inputs = np.random.rand(*inputShape) - else: - info = np.iinfo(dtype) - test_inputs = np.arange(stop = np.prod(inputShape), dtype = dtype).reshape(inputShape) - test_outputs = test_inputs - generateTestNetwork(deployer, [test_inputs], [test_outputs], testRunner._dir_gen, _NoVerbosity) - -# Deconstructed testRunner.run() with skipped generation because we did the generation already -testRunner.configure_cmake_project() -testRunner.build_binary() -if not testRunner._args.skipsim: - testRunner.run_simulation() diff --git a/DeeployTest/testRunner_snitch.py b/DeeployTest/testRunner_snitch.py deleted file mode 100644 index 42a7353818..0000000000 --- a/DeeployTest/testRunner_snitch.py +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = False, description = "Deeploy Code Generation Utility for the Snitch Platform (no Tiling).") - - parser.add_argument('--cores', - metavar = '', - dest = 'cores', - type = int, - default = 9, - help = 'Set number of cluster cores') - parser.add_argument('--simulator', - metavar = "", - dest = "simulator", - type = str, - choices = ["gvsoc", "banshee", "vsim", "vsim.gui"], - default = "gvsoc", - help = "Select the simulator to use") - args = parser.parse_args() - - testRunner = TestRunner(platform = "Snitch", simulator = args.simulator, tiling = False, argument_parser = parser) - - testRunner.cmake_args += f" -D NUM_CORES={args.cores}" - testRunner.run() diff --git a/DeeployTest/testRunner_snitch_dma.py b/DeeployTest/testRunner_snitch_dma.py deleted file mode 100644 index 80073ac5ed..0000000000 --- a/DeeployTest/testRunner_snitch_dma.py +++ /dev/null @@ -1,104 +0,0 @@ -# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -import os - -import numpy as np -from testUtils.codeGenerate import generateTestNetwork -from testUtils.dmaUtils import MemcpyLayer, MemcpyParser, MemcpyTileConstraint, MemcpyTypeChecker, generate_graph, \ - memcpyTemplate, prepare_deployer_with_custom_tiling, setup_snitch_deployer -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser -from testUtils.typeMapping import baseTypeFromName, dtypeFromDeeployType - -from Deeploy.AbstractDataTypes import PointerClass -from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ - MemoryManagementGeneration -from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeMapper, _NoVerbosity -from Deeploy.Targets.Snitch.Bindings import MemoryAwareFunctionCallClosure, TilingCallClosure -from Deeploy.Targets.Snitch.CodeTransformationPasses import SnitchClusterTiling -from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchClusterSynch import SnitchSynchCoresPass -from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchCoreFilter import SnitchCoreFilterPass -from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchProfileExecutionBlock import SnitchProfileExecutionBlockPass -from Deeploy.Targets.Snitch.DMA.SnitchDma import SnitchDma -from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ - TilingVariableReplacementUpdate -from Deeploy.TilingExtension.TilerExtension import TilingReadyNodeBindings - -testRunnerArgumentParser = TestRunnerArgumentParser(tiling_arguments = True) -testRunnerArgumentParser.add_argument('--input-shape', - nargs = '+', - required = True, - dest = 'input_shape', - type = int, - help = "Shape of the copied tensor") -testRunnerArgumentParser.add_argument('--tile-shape', - nargs = '+', - required = True, - dest = 'tile_shape', - type = int, - help = "Shape of the tiles produced in the manual tiling solution") -testRunnerArgumentParser.add_argument('--node-count', - dest = 'node_count', - type = int, - default = 1, - help = "Number of generated memcpy nodes") -testRunnerArgumentParser.add_argument('--type', type = str, default = "uint8_t", help = "Tensor elements datatype") -testRunner = TestRunner('Snitch', 'gvsoc', tiling = True, argument_parser = testRunnerArgumentParser) - -inputShape = testRunner._args.input_shape -tileShape = testRunner._args.tile_shape -node_count = testRunner._args.node_count -_type = baseTypeFromName(testRunner._args.type) -dtype = dtypeFromDeeployType(_type) -defaultMemory = "L2" -targetMemory = "L1" - -assert len(inputShape) == len(tileShape), \ - f'Input and tile shape should be of the same dimensionality. Received {len(inputShape)}D input shape vs. {len(tileShape)}D tile shape.' -assert all(tileDim <= inDim for inDim, tileDim in zip(inputShape, tileShape)), \ - f'Each tile shape dimension should be smaller then the corresponding input one. Received {tileShape} > {inputShape}' - -graph = generate_graph(node_count, inputShape, dtype) -inputTypes = {"input_0": PointerClass(_type)} -_DEEPLOYSTATEDIR = os.path.join(testRunner._dir_gen, "deeployStates") -deployer = setup_snitch_deployer(defaultMemory, targetMemory, graph, inputTypes, testRunner._args.doublebuffer, - _DEEPLOYSTATEDIR) - -transformer = CodeTransformation([ - SnitchCoreFilterPass("compute"), - SnitchProfileExecutionBlockPass(), - TilingVariableReplacement(targetMemory), - TilingCallClosure(writeback = False), - SnitchSynchCoresPass(), - TilingVariableReplacementUpdate(targetMemory), - SnitchClusterTiling(defaultMemory, targetMemory, SnitchDma()), - ArgumentStructGeneration(), - MemoryManagementGeneration(targetMemory), - MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), - MemoryManagementGeneration(defaultMemory), - MemoryManagementGeneration(), -]) - -binding = NodeBinding(MemcpyTypeChecker(), memcpyTemplate, transformer) -tilingReadyBindings = TilingReadyNodeBindings([binding], MemcpyTileConstraint()) -memcpyMapper = NodeMapper(MemcpyParser(), tilingReadyBindings) -memcpyMapping = {"Memcpy": MemcpyLayer([memcpyMapper])} -deployer.Platform.engines[0].Mapping.update(memcpyMapping) - -prepare_deployer_with_custom_tiling(deployer, defaultMemory, targetMemory, tileShape, testRunner._args.doublebuffer) - -if not testRunner._args.skipgen: - if dtype == np.float32: - test_inputs = np.random.rand(*inputShape) - else: - info = np.iinfo(dtype) - test_inputs = np.arange(stop = np.prod(inputShape), dtype = dtype).reshape(inputShape) - test_outputs = test_inputs - generateTestNetwork(deployer, [test_inputs], [test_outputs], testRunner._dir_gen, _NoVerbosity) - -# Deconstructed testRunner.run() with skipped generation because we did the generation already -testRunner.configure_cmake_project() -testRunner.build_binary() -if not testRunner._args.skipsim: - testRunner.run_simulation() diff --git a/DeeployTest/testRunner_softhier.py b/DeeployTest/testRunner_softhier.py deleted file mode 100644 index 9350dce4cf..0000000000 --- a/DeeployTest/testRunner_softhier.py +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - parser = TestRunnerArgumentParser( - tiling_arguments = False, - description = "Deeploy Code Generation Utility for the Single Cluster SoftHier (no Tiling).") - - parser.add_argument('--num_clusters', - metavar = 'num_clusters', - dest = 'num_clusters', - type = int, - default = 1, - help = 'Number of clusters\n') - - parser.add_argument('--verbose', metavar = 'verbose', dest = 'verbose', type = int, default = 2, help = 'verbose\n') - - for action in parser._actions: - if action.dest == 'toolchain_install_dir': - action.default = "${SOFTHIER_INSTALL_DIR}/third_party/toolchain/install" - args = parser.parse_args() - - testRunner = TestRunner(platform = "SoftHier", simulator = "gvsoc", tiling = False, argument_parser = parser) - - testRunner.cmake_args += f" -D num_clusters={args.num_clusters}" - - testRunner.run() diff --git a/DeeployTest/testRunner_tiled_siracusa.py b/DeeployTest/testRunner_tiled_siracusa.py deleted file mode 100644 index 7bf08b7b28..0000000000 --- a/DeeployTest/testRunner_tiled_siracusa.py +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = True, description = "Deeploy Code Generation Utility for the Siracusa Platform (Tiling).") - - parser.add_argument('--cores', - metavar = '', - dest = 'cores', - type = int, - default = 8, - help = 'Set number of cluster cores') - args = parser.parse_args() - - testRunner = TestRunner(platform = "Siracusa", simulator = "gvsoc", tiling = True, argument_parser = parser) - - testRunner.cmake_args += f" -D NUM_CORES={args.cores}" - - testRunner.run() diff --git a/DeeployTest/testRunner_tiled_siracusa_w_neureka.py b/DeeployTest/testRunner_tiled_siracusa_w_neureka.py deleted file mode 100644 index 435f32b895..0000000000 --- a/DeeployTest/testRunner_tiled_siracusa_w_neureka.py +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser( - tiling_arguments = True, - description = "Deeploy Code Generation Utility for the Siracusa Platform (Tiling & NEureka).") - - parser.add_argument('--cores', - metavar = '', - dest = 'cores', - type = int, - default = 8, - help = 'Set number of cluster cores') - parser.add_argument('--neureka-wmem', - dest = "neureka_wmem", - action = "store_true", - default = False, - help = 'Adds weight memory and neureka engine color\n') - parser.add_argument('--enable-3x3', - dest = "enable_3x3", - action = "store_true", - default = False, - help = 'Adds EXPERIMENTAL support for 3x3 convolutions on N-EUREKA\n') - parser.add_argument('--enableStrides', - dest = "enableStrides", - action = "store_true", - default = False, - help = 'Adds EXPERIMENTAL support for strided convolutions on N-EUREKA\n') - args = parser.parse_args() - - testRunner = TestRunner(platform = "Siracusa_w_neureka", - simulator = "gvsoc", - tiling = True, - argument_parser = parser) - - testRunner.cmake_args += f" -D NUM_CORES={args.cores}" - if args.neureka_wmem: - testRunner.gen_args += " --neureka-wmem" - if args.enable_3x3: - testRunner.gen_args += " --enable-3x3" - if args.enableStrides: - testRunner.gen_args += " --enableStrides" - - testRunner.run() diff --git a/DeeployTest/testRunner_tiled_snitch.py b/DeeployTest/testRunner_tiled_snitch.py deleted file mode 100644 index 7787d1f844..0000000000 --- a/DeeployTest/testRunner_tiled_snitch.py +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna -# -# SPDX-License-Identifier: Apache-2.0 - -from testUtils.testRunner import TestRunner, TestRunnerArgumentParser - -if __name__ == "__main__": - - parser = TestRunnerArgumentParser(tiling_arguments = True, - description = "Deeploy Code Generation Utility for the Snitch Platform (Tiling).") - - parser.add_argument('--cores', - metavar = '', - dest = 'cores', - type = int, - default = 9, - help = 'Set number of cluster cores') - parser.add_argument('--simulator', - metavar = "", - dest = "simulator", - type = str, - choices = ["gvsoc", "banshee", "vsim", "vsim.gui"], - default = "gvsoc", - help = "Select the simulator to use") - - args = parser.parse_args() - - testRunner = TestRunner(platform = "Snitch", simulator = args.simulator, tiling = True, argument_parser = parser) - - testRunner.cmake_args += f" -D NUM_CORES={args.cores}" - - testRunner.run() diff --git a/DeeployTest/testUtils/pytestRunner.py b/DeeployTest/testUtils/pytestRunner.py new file mode 100644 index 0000000000..09d19da735 --- /dev/null +++ b/DeeployTest/testUtils/pytestRunner.py @@ -0,0 +1,488 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import re +import shutil +import subprocess +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import List, Literal, Optional, Tuple + +from Deeploy.Logging import DEFAULT_LOGGER as log + + +@dataclass +class DeeployTestConfig: + """Configuration for a single test case.""" + test_name: str + test_dir: str + platform: str + simulator: Literal['gvsoc', 'banshee', 'qemu', 'vsim', 'vsim.gui', 'host', 'none'] + tiling: bool + gen_dir: str + build_dir: str + toolchain: str = "LLVM" + toolchain_install_dir: Optional[str] = None + cmake_args: List[str] = None + gen_args: List[str] = None + verbose: int = 0 + debug: bool = False + + def __post_init__(self): + if self.cmake_args is None: + self.cmake_args = [] + if self.gen_args is None: + self.gen_args = [] + if self.toolchain_install_dir is None: + self.toolchain_install_dir = os.environ.get('LLVM_INSTALL_DIR') + + +@dataclass +class TestResult: + """Results from running a test.""" + success: bool + error_count: int + total_count: int + stdout: str + stderr: str = "" + runtime_cycles: Optional[int] = None + + +def get_test_paths(test_dir: str, platform: str, base_dir: Optional[str] = None) -> Tuple[str, str, str]: + """ + Args: + test_dir: Path to test directory (e.g., "Tests/Adder" or absolute path) + platform: Platform name (e.g., "Generic") + base_dir: Base directory for tests (defaults to DeeployTest/) + + Returns: + Tuple of (gen_dir, test_dir_abs, test_name) + """ + if base_dir is None: + # Get the absolute path of this script's parent directory (testUtils -> DeeployTest) + script_path = Path(__file__).resolve() + base_dir = script_path.parent.parent + else: + base_dir = Path(base_dir) + + test_path = Path(test_dir) + if not test_path.is_absolute(): + test_path = base_dir / test_dir + + test_path = test_path.resolve() + test_name = test_path.name + + gen_dir_name = f"TEST_{platform.upper()}" + + # Check if path is inside base_dir + try: + rel_path = test_path.relative_to(base_dir) + gen_dir = base_dir / gen_dir_name / rel_path + except ValueError: + # Path is outside base_dir + gen_dir = base_dir / gen_dir_name / test_name + log.warning(f"Test path {test_path} is outside base directory. Using {gen_dir}") + + return str(gen_dir), str(test_path), test_name + + +def generate_network(config: DeeployTestConfig, skip: bool = False) -> None: + """ + Args: + config: Test configuration + skip: If True, skip generation (useful for re-running tests) + + Raises: + RuntimeError: If network generation fails + """ + if skip: + log.info(f"Skipping network generation for {config.test_name}") + return + + script_dir = Path(__file__).parent.parent + + if config.tiling: + generation_script = script_dir / "testMVP.py" + else: + generation_script = script_dir / "generateNetwork.py" + + cmd = [ + "python", + str(generation_script), + "-d", + config.gen_dir, + "-t", + config.test_dir, + "-p", + config.platform, + ] + + # Add verbosity flags + if config.verbose > 0: + cmd.append("-" + "v" * config.verbose) + + # Add debug flag + if config.debug: + cmd.append("--debug") + + # Add additional generation arguments + cmd.extend(config.gen_args) + + log.debug(f"[pytestRunner] Generation command: {' '.join(cmd)}") + + result = subprocess.run(cmd, check = False) + + if result.returncode != 0: + log.error(f"Network generation failed with return code {result.returncode}") + raise RuntimeError(f"Network generation failed for {config.test_name}") + + +def configure_cmake(config: DeeployTestConfig) -> None: + """ + Args: + config: Test configuration + + Raises: + RuntimeError: If CMake configuration fails + """ + assert config.toolchain_install_dir is not None, \ + "LLVM_INSTALL_DIR environment variable not set" + + cmake_cmd = os.environ.get("CMAKE", "cmake") + if cmake_cmd == "cmake" and shutil.which("cmake") is None: + raise RuntimeError("CMake not found. Please install CMake or set CMAKE environment variable") + + # Build CMake command + cmd = [ + cmake_cmd, + f"-DTOOLCHAIN={config.toolchain}", + f"-DTOOLCHAIN_INSTALL_DIR={config.toolchain_install_dir}", + f"-DGENERATED_SOURCE={config.gen_dir}", + f"-Dplatform={config.platform}", + f"-DTESTNAME={config.test_name}", + f"-B{config.build_dir}", + ] + + # Add custom CMake arguments + for arg in config.cmake_args: + if not arg.startswith("-D"): + arg = "-D" + arg + cmd.append(arg) + + # Add simulator flags + if config.simulator == 'banshee': + cmd.append("-Dbanshee_simulation=ON") + else: + cmd.append("-Dbanshee_simulation=OFF") + + if config.simulator == 'gvsoc': + cmd.append("-Dgvsoc_simulation=ON") + else: + cmd.append("-Dgvsoc_simulation=OFF") + + # Last argument is the source directory + script_dir = Path(__file__).parent.parent + cmd.append(str(script_dir.parent)) + + env = os.environ.copy() + if config.verbose >= 3: + env["VERBOSE"] = "1" + + log.debug(f"[pytestRunner] CMake command: {' '.join(cmd)}") + + result = subprocess.run(cmd, check = False, env = env) + + if result.returncode != 0: + log.error(f"CMake configuration failed with return code {result.returncode}") + raise RuntimeError(f"CMake configuration failed for {config.test_name}") + + +def build_binary(config: DeeployTestConfig) -> None: + """ + Args: + config: Test configuration + + Raises: + RuntimeError: If build fails + """ + cmake_cmd = os.environ.get("CMAKE", "cmake") + + cmd = [ + cmake_cmd, + "--build", + config.build_dir, + "--target", + config.test_name, + ] + + env = os.environ.copy() + if config.verbose >= 3: + env["VERBOSE"] = "1" + + log.debug(f"[pytestRunner] Build command: {' '.join(cmd)}") + + result = subprocess.run(cmd, check = False, env = env) + + if result.returncode != 0: + log.error(f"Build failed with return code {result.returncode}") + raise RuntimeError(f"Build failed for {config.test_name}") + + +def run_simulation(config: DeeployTestConfig, skip: bool = False) -> TestResult: + """ + Args: + config: Test configuration + skip: If True, skip simulation (useful for build-only tests) + + Returns: + TestResult with parsed output + + Raises: + RuntimeError: If simulation cannot be executed + """ + if skip: + log.info(f"Skipping simulation for {config.test_name}") + return TestResult(success = True, error_count = 0, total_count = 0, stdout = "Skipped") + + if config.simulator == 'none': + raise RuntimeError("No simulator specified!") + + if config.simulator == 'host': + # Run binary directly + binary_path = Path(config.build_dir) / "bin" / config.test_name + cmd = [str(binary_path)] + else: + # Run via CMake target + cmake_cmd = os.environ.get("CMAKE", "cmake") + cmd = [ + cmake_cmd, + "--build", + config.build_dir, + "--target", + f"{config.simulator}_{config.test_name}", + ] + + env = os.environ.copy() + if config.verbose >= 3: + env["VERBOSE"] = "1" + + # Add banshee-specific logging + if config.simulator == 'banshee': + if config.verbose == 1: + env["BANSHEE_LOG"] = "warn" + elif config.verbose == 2: + env["BANSHEE_LOG"] = "info" + elif config.verbose >= 3: + env["BANSHEE_LOG"] = "debug" + + log.debug(f"[pytestRunner] Simulation command: {' '.join(cmd)}") + + result = subprocess.run(cmd, capture_output = True, text = True, env = env) + + # Print captured output so it's visible when running with pytest -s + if result.stdout: + print(result.stdout, end = '') + if result.stderr: + print(result.stderr, end = '', file = sys.stderr) + + # Parse output for error count + output = result.stdout + result.stderr + + # Look for "Errors: X out of Y" pattern + error_match = re.search(r'Errors:\s*(\d+)\s*out\s*of\s*(\d+)', output) + + if error_match: + error_count = int(error_match.group(1)) + total_count = int(error_match.group(2)) + success = (error_count == 0) + else: + # Could not parse output - treat as failure + log.warning(f"Could not parse error count from output:\n{output}") + error_count = -1 + total_count = -1 + success = False + + # Try to parse runtime cycles + runtime_cycles = None + cycle_match = re.search(r'Runtime:\s*(\d+)\s*cycles', output) + if cycle_match: + runtime_cycles = int(cycle_match.group(1)) + + return TestResult( + success = success, + error_count = error_count, + total_count = total_count, + stdout = result.stdout, + stderr = result.stderr, + runtime_cycles = runtime_cycles, + ) + + +def run_complete_test(config: DeeployTestConfig, skipgen: bool = False, skipsim: bool = False) -> TestResult: + """ + Run a complete test: generate, configure, build, and simulate. + + Args: + config: Test configuration + skipgen: Skip network generation + skipsim: Skip simulation + + Returns: + TestResult with parsed output + """ + log.info(f"################## Testing {config.test_name} on {config.platform} Platform ##################") + + # Step 1: Generate network + generate_network(config, skip = skipgen) + + # Step 2: Configure CMake + configure_cmake(config) + + # Step 3: Build binary + build_binary(config) + + # Step 4: Run simulation + result = run_simulation(config, skip = skipsim) + + return result + + +def get_worker_id() -> str: + """ + Get the pytest-xdist worker ID for parallel test execution. + + Returns: + Worker ID string (e.g., 'gw0', 'gw1', 'master' for non-parallel) + """ + return os.environ.get("PYTEST_XDIST_WORKER", "master") + + +def create_test_config( + test_name: str, + platform: str, + simulator: Literal['gvsoc', 'banshee', 'qemu', 'vsim', 'vsim.gui', 'host', 'none'], + deeploy_test_dir: str, + toolchain: str, + toolchain_dir: Optional[str], + cmake_args: List[str], + tiling: bool = False, + cores: Optional[int] = None, + l1: Optional[int] = None, + l2: int = 1024000, + default_mem_level: str = "L2", + double_buffer: bool = False, + mem_alloc_strategy: str = "MiniMalloc", + search_strategy: str = "random-max", + profile_tiling: bool = False, + plot_mem_alloc: bool = False, + randomized_mem_scheduler: bool = False, + gen_args: Optional[List[str]] = None, +) -> DeeployTestConfig: + """ + Create DeeployTestConfig for a specific test and platform. + + Args: + test_name: Name of the test + platform: Target platform (e.g., "Generic", "QEMU-ARM", "Siracusa") + simulator: Simulator to use + deeploy_test_dir: Base DeeployTest directory + toolchain: Toolchain to use - LLVM/GCC + toolchain_dir: Path to toolchain installation + cmake_args: Additional CMake arguments + tiling: Whether to use tiling + cores: Number of cores (for Siracusa platforms) + l1: L1 memory size in bytes (for tiled platforms) + l2: L2 memory size in bytes (default: 1024000) + default_mem_level: Default memory level ("L2" or "L3") + double_buffer: Enable double buffering + mem_alloc_strategy: Memory allocation strategy + search_strategy: CP solver search strategy + profile_tiling: Enable tiling profiling + plot_mem_alloc: Enable memory allocation plotting + randomized_mem_scheduler: Enable randomized memory scheduler + + Returns: + DeeployTestConfig instance + """ + test_dir = f"Tests/{test_name}" + + gen_dir, test_dir_abs, test_name_clean = get_test_paths(test_dir, platform, base_dir = deeploy_test_dir) + + worker_id = get_worker_id() + + # Build directory: shared per worker, not per test (for ccache efficiency) + # Only add worker suffix for parallel execution (worker_id != "master") + if worker_id == "master": + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / "build_master") + else: + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / f"build_{worker_id}") + + cmake_args_list = list(cmake_args) if cmake_args else [] + if cores is not None: + cmake_args_list.append(f"NUM_CORES={cores}") + + gen_args_list = list(gen_args) if gen_args else [] + + if cores is not None and platform in ["Siracusa", "Siracusa_w_neureka"]: + gen_args_list.append(f"--cores={cores}") + + if tiling: + if l1 is not None: + gen_args_list.append(f"--l1={l1}") + if l2 != 1024000: + gen_args_list.append(f"--l2={l2}") + if default_mem_level != "L2": + gen_args_list.append(f"--defaultMemLevel={default_mem_level}") + if double_buffer: + gen_args_list.append("--doublebuffer") + if mem_alloc_strategy != "MiniMalloc": + gen_args_list.append(f"--memAllocStrategy={mem_alloc_strategy}") + if search_strategy != "random-max": + gen_args_list.append(f"--searchStrategy={search_strategy}") + if profile_tiling: + gen_args_list.append("--profileTiling") + if plot_mem_alloc: + gen_args_list.append("--plotMemAlloc") + if randomized_mem_scheduler: + gen_args_list.append("--randomizedMemoryScheduler") + + config = DeeployTestConfig( + test_name = test_name_clean, + test_dir = test_dir_abs, + platform = platform, + simulator = simulator, + tiling = tiling, + gen_dir = gen_dir, + build_dir = build_dir, + toolchain = toolchain, + toolchain_install_dir = toolchain_dir, + cmake_args = cmake_args_list, + gen_args = gen_args_list, + ) + + return config + + +def run_and_assert_test(test_name: str, config: DeeployTestConfig, skipgen: bool, skipsim: bool) -> None: + """ + Shared helper function to run a test and assert its results. + + Args: + test_name: Name of the test + config: DeeployTestConfig instance + skipgen: Whether to skip network generation + skipsim: Whether to skip simulation + + Raises: + AssertionError: If test fails or has errors + """ + result = run_complete_test(config, skipgen = skipgen, skipsim = skipsim) + + assert result.success, (f"Test {test_name} failed with {result.error_count} errors out of {result.total_count}\n" + f"Output:\n{result.stdout}") + + if result.error_count >= 0: + assert result.error_count == 0, (f"Found {result.error_count} errors out of {result.total_count} tests") diff --git a/DeeployTest/test_chimera_config.py b/DeeployTest/test_chimera_config.py new file mode 100644 index 0000000000..bcc846cb75 --- /dev/null +++ b/DeeployTest/test_chimera_config.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Chimera platform.""" + +# Chimera platform uses gvsoc simulator +# Currently only Adder test is in CI + +KERNEL_TESTS = [ + "Kernels/Integer/Add/Regular", +] + +MODEL_TESTS = [] diff --git a/DeeployTest/test_cortexm_config.py b/DeeployTest/test_cortexm_config.py new file mode 100644 index 0000000000..dbbd2e4758 --- /dev/null +++ b/DeeployTest/test_cortexm_config.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Cortex-M (QEMU-ARM) platform.""" + +KERNEL_TESTS = [ + "Kernels/Integer/Add/Regular", + "Kernels/Integer/Add/MultIO", + "Kernels/Integer/Pad/Regular_1D", + "Kernels/Integer/Pad/Regular_2D", + "Kernels/Integer/MatMul/Regular", + "Kernels/Integer/MatMul/Add", + "Kernels/Integer/MaxPool", + "Kernels/Integer/Conv/Regular_2D_RQ", + "Kernels/Integer/ReduceSum", + "Kernels/Integer/ReduceMean", + "Kernels/Integer/Slice", +] + +MODEL_TESTS = [ + "Models/CNN_Linear2", + "Models/WaveFormer", +] diff --git a/DeeployTest/test_deeploy_internal.py b/DeeployTest/test_deeploy_internal.py new file mode 100644 index 0000000000..14f7c3fc15 --- /dev/null +++ b/DeeployTest/test_deeploy_internal.py @@ -0,0 +1,372 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +import subprocess +from pathlib import Path + +import pytest + +# Mark all tests in this module as deeploy_internal +pytestmark = pytest.mark.deeploy_internal + + +@pytest.mark.parametrize("platform", ["QEMU-ARM", "Siracusa", "MemPool", "Generic"]) +def test_deeploy_state_serialization(platform): + """Test that Deeploy state can be serialized and deserialized correctly.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "deeployStateEqualityTest.py"), + "-t", + "./Tests/Models/CNN_Linear2", + "-p", + platform, + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"State serialization test failed for platform {platform}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +@pytest.mark.parametrize("platform", ["QEMU-ARM", "Siracusa", "MemPool", "Generic"]) +def test_memory_level_extension(platform): + """Test memory level extension functionality.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testMemoryLevelExtension.py"), + "-t", + "./Tests/Models/CNN_Linear2", + "-p", + platform, + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Memory level extension test failed for platform {platform}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +class TestMemoryAllocation: + """Test memory allocation strategies and constraints.""" + + def test_minimalloc_sufficient_memory(self): + """Test MiniMalloc strategy with sufficient L2 memory.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testMVP.py"), + "-t", + "Tests/Models/CCT/FP32/CCT_1_16_16_8", + "-p", + "Siracusa", + "--defaultMemLevel=L2", + "--l1=64000", + "--l2=75000", + "--memAllocStrategy=MiniMalloc", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Memory allocation test (MiniMalloc, L2=75000) failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_minimalloc_insufficient_memory(self): + """Test that MiniMalloc correctly fails with insufficient L2 memory.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testMVP.py"), + "-t", + "Tests/Models/CCT/FP32/CCT_1_16_16_8", + "-p", + "Siracusa", + "--defaultMemLevel=L2", + "--l1=64000", + "--l2=60000", + "--memAllocStrategy=MiniMalloc", + "--shouldFail", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, ( + f"Memory allocation test (MiniMalloc should fail, L2=60000) did not behave as expected\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_tetrisrandom_sufficient_memory(self): + """Test TetrisRandom strategy with sufficient L2 memory.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testMVP.py"), + "-t", + "Tests/Models/CCT/FP32/CCT_1_16_16_8", + "-p", + "Siracusa", + "--defaultMemLevel=L2", + "--l1=64000", + "--l2=90000", + "--memAllocStrategy=TetrisRandom", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Memory allocation test (TetrisRandom, L2=90000) failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_tetrisrandom_insufficient_memory(self): + """Test that TetrisRandom correctly fails with insufficient L2 memory.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testMVP.py"), + "-t", + "Tests/Models/CCT/FP32/CCT_1_16_16_8", + "-p", + "Siracusa", + "--defaultMemLevel=L2", + "--l1=64000", + "--l2=75000", + "--memAllocStrategy=TetrisRandom", + "--shouldFail", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, ( + f"Memory allocation test (TetrisRandom should fail, L2=75000) did not behave as expected\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +class TestTilerExtension: + """Test tiling extension functionality.""" + + @pytest.mark.parametrize("test_path", [ + "./Tests/Models/CNN_Linear2", + "./Tests/Models/CNN_Linear1", + "./Tests/Kernels/Integer/MatMul/Regular", + "./Tests/Kernels/Integer/MaxPool", + ]) + def test_tiler_basic(self, test_path): + """Test that tiler can process various networks without L1 constraints.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testTilerExtension.py"), + "-p", + "Siracusa", + "-t", + test_path, + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Tiler extension test failed for {test_path}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + @pytest.mark.parametrize("test_path", [ + "./Tests/Models/CNN_Linear2", + "./Tests/Models/CNN_Linear1", + "./Tests/Kernels/Integer/MatMul/Regular", + "./Tests/Kernels/Integer/MaxPool", + ]) + def test_tiler_constrained_should_fail(self, test_path): + """Test that tiler correctly fails when L1 memory is too small.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testTilerExtension.py"), + "-p", + "Siracusa", + "-t", + test_path, + "--l1", + "2000", + "--shouldFail", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, ( + f"Tiler extension test (should fail) did not behave as expected for {test_path}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + @pytest.mark.parametrize("test_path", [ + "./Tests/Models/CNN_Linear2", + "./Tests/Models/CNN_Linear1", + "./Tests/Models/miniMobileNet", + "./Tests/Models/miniMobileNetv2", + "./Tests/Kernels/Integer/MatMul/Regular", + "./Tests/Kernels/Integer/MaxPool", + ]) + def test_tiler_double_buffer(self, test_path): + """Test tiler with double buffering enabled.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testTilerExtension.py"), + "-p", + "Siracusa", + "-t", + test_path, + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Tiler extension test (double buffer) failed for {test_path}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +def test_types(): + """Test Deeploy type system (serialization, equivalence, promotion).""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testTypes.py"), + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Types test failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +class TestDebugTransformations: + """Test debug and diagnostic transformations.""" + + @pytest.mark.parametrize("platform", ["Generic", "Siracusa"]) + def test_print_input_output_transformation(self, platform): + """Test print input/output transformation for debugging.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testPrintInputOutputTransformation.py"), + "-p", + platform, + "-t", + "./Tests/Models/CNN_Linear2", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Print I/O transformation test failed for platform {platform}\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_debug_print_pass(self): + """Test debug print pass transformation.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testDebugPrintPass.py"), + "-p", + "Generic", + "-t", + "./Tests/Models/CNN_Linear2", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Debug print pass test failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +def test_regex_matching(): + """Test regex matching utilities.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "testRegexMatching.py"), + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Regex matching test failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + +class TestTypeInference: + """Test type inference functionality with different input type configurations.""" + + def test_type_inference_fail_all_int8(self): + """Test that type inference correctly fails when all inputs are int8.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "generateNetwork.py"), + "-p", + "Generic", + "-t", + "./Tests/Others/TypeInference", + "-v", + "--input-type-map", + "A=int8_t", + "B=int8_t", + "C=int8_t", + "--input-offset-map", + "A=0", + "B=0", + "C=0", + "--shouldFail", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Type inference test (should fail with all int8) did not behave as expected\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_type_inference_fail_incompatible_output(self): + """Test that type inference correctly fails with incompatible output type.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "generateNetwork.py"), + "-p", + "Generic", + "-t", + "./Tests/Others/TypeInference", + "-v", + "--input-type-map", + "A=int16_t", + "B=int8_t", + "C=int16_t", + "--input-offset-map", + "A=0", + "B=0", + "C=0", + "--shouldFail", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, ( + f"Type inference test (should fail with incompatible output) did not behave as expected\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") + + def test_type_inference_pass(self): + """Test that type inference succeeds with correct type configuration.""" + script_dir = Path(__file__).parent + cmd = [ + "python", + str(script_dir / "generateNetwork.py"), + "-p", + "Generic", + "-t", + "./Tests/Others/TypeInference", + "-v", + "--input-type-map", + "A=int16_t", + "B=int8_t", + "C=int32_t", + "--input-offset-map", + "A=0", + "B=0", + "C=0", + ] + result = subprocess.run(cmd, cwd = script_dir, capture_output = True, text = True) + + assert result.returncode == 0, (f"Type inference test (should pass) failed\n" + f"stdout: {result.stdout}\n" + f"stderr: {result.stderr}") diff --git a/DeeployTest/test_dmas.py b/DeeployTest/test_dmas.py new file mode 100644 index 0000000000..938459ae62 --- /dev/null +++ b/DeeployTest/test_dmas.py @@ -0,0 +1,372 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""DMA test suite for Siracusa and Snitch platforms. + +Tests three DMA implementations across various tensor shapes and configurations: +- MchanDma: Siracusa L2→L1 DMA transfers +- L3Dma: Siracusa L3→L2 DMA transfers +- SnitchDma: Snitch L2→L1 DMA transfers + +Total test matrix: 3 DMAs × 10 shapes × 2 buffering modes = 60 tests +""" + +import os +from pathlib import Path + +import numpy as np +import pytest +from testUtils.codeGenerate import generateTestNetwork +from testUtils.dmaUtils import MemcpyLayer, MemcpyParser, MemcpyTileConstraint, MemcpyTypeChecker, generate_graph, \ + memcpyTemplate, prepare_deployer_with_custom_tiling, setup_pulp_deployer, setup_snitch_deployer +from testUtils.pytestRunner import build_binary, configure_cmake, get_test_paths, get_worker_id +from testUtils.typeMapping import baseTypeFromName, dtypeFromDeeployType + +from Deeploy.AbstractDataTypes import PointerClass +from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ + MemoryManagementGeneration +from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeMapper, _NoVerbosity +from Deeploy.Targets.PULPOpen.Bindings import L3MemoryAwareFunctionCallClosure +from Deeploy.Targets.PULPOpen.Bindings import MemoryAwareFunctionCallClosure as PULPMemoryAwareFunctionCallClosure +from Deeploy.Targets.PULPOpen.Bindings import TilingCallClosure as PULPTilingCallClosure +from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterTiling import PULPClusterTiling +from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3Tiling import PULPL3Tiling +from Deeploy.Targets.PULPOpen.DMA.L3Dma import L3Dma, l3DmaHack +from Deeploy.Targets.PULPOpen.DMA.MchanDma import MchanDma +from Deeploy.Targets.Snitch.Bindings import MemoryAwareFunctionCallClosure, TilingCallClosure +from Deeploy.Targets.Snitch.CodeTransformationPasses import SnitchClusterTiling +from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchClusterSynch import SnitchSynchCoresPass +from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchCoreFilter import SnitchCoreFilterPass +from Deeploy.Targets.Snitch.CodeTransformationPasses.SnitchProfileExecutionBlock import SnitchProfileExecutionBlockPass +from Deeploy.Targets.Snitch.DMA.SnitchDma import SnitchDma +from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ + TilingVariableReplacementUpdate +from Deeploy.TilingExtension.TilerExtension import TilingReadyNodeBindings + + +@pytest.fixture(autouse = True) +def clear_deeploy_state(): + """Clear dynamically generated struct classes from AbstractDataTypes before each test. + + This prevents state pollution between DMA tests where dynamically generated + struct classes (like _memcpy_0_tiling_closure_args_t) persist and cause + conflicts when tests with different configurations try to create new versions. + """ + import Deeploy.AbstractDataTypes as ADT + + # Get list of all attributes before test + attrs_to_remove = [] + for attr_name in dir(ADT): + # Remove dynamically generated struct classes (closure args, etc.) + if attr_name.startswith('_') and ('closure_args' in attr_name or 'memcpy' in attr_name.lower()): + attr = getattr(ADT, attr_name, None) + if isinstance(attr, type): + attrs_to_remove.append(attr_name) + + # Remove stale struct classes + for attr_name in attrs_to_remove: + delattr(ADT, attr_name) + + yield # Run the test + + # Clean up after test as well + for attr_name in dir(ADT): + if attr_name.startswith('_') and ('closure_args' in attr_name or 'memcpy' in attr_name.lower()): + attr = getattr(ADT, attr_name, None) + if isinstance(attr, type): + try: + delattr(ADT, attr_name) + except AttributeError: + pass + + +# Test shape configurations: (input_shape, tile_shape, node_count, data_type) +DMA_TEST_SHAPES = [ + ((10, 10), (10, 10), 1, "uint8_t"), + ((10, 10), (10, 4), 1, "uint8_t"), + ((10, 10), (10, 4), 1, "uint16_t"), + ((10, 10), (10, 4), 1, "uint32_t"), + ((10, 10), (3, 4), 1, "uint32_t"), + ((10, 10), (3, 4), 2, "uint32_t"), + ((10, 10, 10), (2, 3, 4), 1, "uint8_t"), + ((10, 10, 10, 10), (2, 3, 5, 4), 1, "uint8_t"), + ((10, 10, 10, 10), (2, 3, 5, 4), 1, "uint32_t"), + ((10, 10, 10, 10, 10), (2, 3, 5, 7, 4), 1, "uint8_t"), +] + + +def param_id_dma(val): + """Generate readable test IDs for DMA parametrized tests.""" + if isinstance(val, tuple) and len(val) == 4: + input_shape, tile_shape, node_count, data_type = val + shape_str = "x".join(map(str, input_shape)) + tile_str = "x".join(map(str, tile_shape)) + return f"{shape_str}_tile{tile_str}_n{node_count}_{data_type}" + elif isinstance(val, bool): + return "doublebuffer" if val else "singlebuffer" + return str(val) + + +def setup_dma_deployer(dma_type: str, input_shape: tuple, tile_shape: tuple, node_count: int, data_type: str, + doublebuffer: bool, gen_dir: str): + """ + Set up deployer for DMA testing with custom tiling. + + Args: + dma_type: DMA implementation ("MchanDma", "L3Dma", "SnitchDma") + input_shape: Tensor shape to copy + tile_shape: Tiling dimensions + node_count: Number of memcpy nodes + data_type: Data type (uint8_t, uint16_t, uint32_t) + doublebuffer: Enable double buffering + gen_dir: Generation directory + + Returns: + tuple: (deployer, test_inputs, test_outputs) + """ + _type = baseTypeFromName(data_type) + dtype = dtypeFromDeeployType(_type) + + # Validate shapes + assert len(input_shape) == len(tile_shape), \ + f'Input and tile shape must have same dimensionality: {len(input_shape)}D vs {len(tile_shape)}D' + assert all(tileDim <= inDim for inDim, tileDim in zip(input_shape, tile_shape)), \ + f'Tile shape {tile_shape} must be <= input shape {input_shape}' + + # DMA-specific configuration + if dma_type == "MchanDma": + defaultMemory = "L2" + targetMemory = "L1" + dma_obj = MchanDma() + elif dma_type == "L3Dma": + defaultMemory = "L3" + targetMemory = "L2" + dma_obj = L3Dma() + elif dma_type == "SnitchDma": + defaultMemory = "L2" + targetMemory = "L1" + dma_obj = SnitchDma() + else: + raise ValueError(f"Unknown DMA type: {dma_type}") + + # Generate graph and setup deployer + graph = generate_graph(node_count, input_shape, dtype) + inputTypes = {"input_0": PointerClass(_type)} + _DEEPLOYSTATEDIR = os.path.join(gen_dir, "deeployStates") + + if dma_type == "SnitchDma": + deployer = setup_snitch_deployer(defaultMemory, targetMemory, graph, inputTypes, doublebuffer, _DEEPLOYSTATEDIR) + else: + deployer = setup_pulp_deployer(defaultMemory, targetMemory, graph, inputTypes, doublebuffer, _DEEPLOYSTATEDIR) + + # Create transformer with DMA-specific passes + if dma_type == "SnitchDma": + transformer = CodeTransformation([ + SnitchCoreFilterPass("compute"), + SnitchProfileExecutionBlockPass(), + TilingVariableReplacement(targetMemory), + TilingCallClosure(writeback = False), + SnitchSynchCoresPass(), + TilingVariableReplacementUpdate(targetMemory), + SnitchClusterTiling(defaultMemory, targetMemory, dma_obj), + ArgumentStructGeneration(), + MemoryManagementGeneration(targetMemory), + MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), + MemoryManagementGeneration(defaultMemory), + MemoryManagementGeneration(), + ]) + elif dma_type == "L3Dma": + # L3Dma uses PULPL3Tiling and L3MemoryAwareFunctionCallClosure + transformer = CodeTransformation([ + TilingVariableReplacement(targetMemory), + PULPTilingCallClosure(writeback = False, generateStruct = True), + TilingVariableReplacementUpdate(targetMemory), + PULPL3Tiling("L3", "L2", l3DmaHack), + ArgumentStructGeneration(), + L3MemoryAwareFunctionCallClosure(writeback = False), + MemoryManagementGeneration("L2"), + MemoryManagementGeneration("L3.*"), + MemoryManagementGeneration(), + ]) + else: # MchanDma + transformer = CodeTransformation([ + TilingVariableReplacement(targetMemory), + PULPTilingCallClosure(writeback = False, generateStruct = True), + TilingVariableReplacementUpdate(targetMemory), + PULPClusterTiling(defaultMemory, targetMemory, dma_obj), + ArgumentStructGeneration(), + MemoryManagementGeneration(targetMemory), + TilingVariableReplacement(defaultMemory), + PULPMemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), + MemoryManagementGeneration(defaultMemory), + MemoryManagementGeneration(), + ]) + + # Set up bindings + binding = NodeBinding(MemcpyTypeChecker(), memcpyTemplate, transformer) + tilingReadyBindings = TilingReadyNodeBindings([binding], MemcpyTileConstraint()) + memcpyMapper = NodeMapper(MemcpyParser(), tilingReadyBindings) + memcpyMapping = {"Memcpy": MemcpyLayer([memcpyMapper])} + deployer.Platform.engines[0].Mapping.update(memcpyMapping) + + # Prepare custom tiling + prepare_deployer_with_custom_tiling(deployer, defaultMemory, targetMemory, tile_shape, doublebuffer) + + # Generate test inputs/outputs + if dtype == np.float32: + test_inputs = np.random.rand(*input_shape) + else: + test_inputs = np.arange(stop = np.prod(input_shape), dtype = dtype).reshape(input_shape) + test_outputs = test_inputs + + return deployer, test_inputs, test_outputs + + +@pytest.mark.deeploy_internal +@pytest.mark.parametrize("test_shape", DMA_TEST_SHAPES, ids = param_id_dma) +@pytest.mark.parametrize("doublebuffer", [True, False], ids = param_id_dma) +def test_mchan_dma(test_shape, doublebuffer, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, + skipsim) -> None: + """Test MchanDma (Siracusa L2→L1 DMA transfers).""" + input_shape, tile_shape, node_count, data_type = test_shape + + # Setup paths + test_name = f"testMchanDma_{param_id_dma(test_shape)}_{param_id_dma(doublebuffer)}" + platform = "Siracusa" + gen_dir, _, test_name_clean = get_test_paths(f"test_dma_gen/{test_name}", platform, base_dir = deeploy_test_dir) + + # Generate network + if not skipgen: + deployer, test_inputs, test_outputs = setup_dma_deployer("MchanDma", input_shape, tile_shape, node_count, + data_type, doublebuffer, gen_dir) + generateTestNetwork(deployer, [test_inputs], [test_outputs], gen_dir, _NoVerbosity) + + # Build and run + worker_id = get_worker_id() + if worker_id == "master": + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / "build_master") + else: + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / f"build_{worker_id}") + + from testUtils.pytestRunner import DeeployTestConfig + config = DeeployTestConfig( + test_name = test_name_clean, + test_dir = gen_dir, + platform = platform, + simulator = 'gvsoc', + tiling = True, + gen_dir = gen_dir, + build_dir = build_dir, + toolchain = toolchain, + toolchain_install_dir = toolchain_dir, + cmake_args = list(cmake_args) + ["NUM_CORES=8"], + ) + + configure_cmake(config) + build_binary(config) + + if not skipsim: + from testUtils.pytestRunner import run_simulation + result = run_simulation(config) + assert result.success, f"MchanDma test failed with {result.error_count} errors" + assert result.error_count == 0, f"Found {result.error_count} errors" + + +@pytest.mark.deeploy_internal +@pytest.mark.parametrize("test_shape", DMA_TEST_SHAPES, ids = param_id_dma) +@pytest.mark.parametrize("doublebuffer", [True, False], ids = param_id_dma) +def test_l3_dma(test_shape, doublebuffer, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, + skipsim) -> None: + """Test L3Dma (Siracusa L3→L2 DMA transfers).""" + input_shape, tile_shape, node_count, data_type = test_shape + + # Setup paths + test_name = f"testL3Dma_{param_id_dma(test_shape)}_{param_id_dma(doublebuffer)}" + platform = "Siracusa" + gen_dir, _, test_name_clean = get_test_paths(f"test_dma_gen/{test_name}", platform, base_dir = deeploy_test_dir) + + # Generate network + if not skipgen: + deployer, test_inputs, test_outputs = setup_dma_deployer("L3Dma", input_shape, tile_shape, node_count, + data_type, doublebuffer, gen_dir) + generateTestNetwork(deployer, [test_inputs], [test_outputs], gen_dir, _NoVerbosity) + + # Build and run + worker_id = get_worker_id() + if worker_id == "master": + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / "build_master") + else: + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / f"build_{worker_id}") + + from testUtils.pytestRunner import DeeployTestConfig + config = DeeployTestConfig( + test_name = test_name_clean, + test_dir = gen_dir, + platform = platform, + simulator = 'gvsoc', + tiling = True, + gen_dir = gen_dir, + build_dir = build_dir, + toolchain = toolchain, + toolchain_install_dir = toolchain_dir, + cmake_args = list(cmake_args) + ["NUM_CORES=8"], + ) + + configure_cmake(config) + build_binary(config) + + if not skipsim: + from testUtils.pytestRunner import run_simulation + result = run_simulation(config) + assert result.success, f"L3Dma test failed with {result.error_count} errors" + assert result.error_count == 0, f"Found {result.error_count} errors" + + +@pytest.mark.deeploy_internal +@pytest.mark.parametrize("test_shape", DMA_TEST_SHAPES, ids = param_id_dma) +@pytest.mark.parametrize("doublebuffer", [True, False], ids = param_id_dma) +def test_snitch_dma(test_shape, doublebuffer, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, + skipsim) -> None: + """Test SnitchDma (Snitch L2→L1 DMA transfers).""" + input_shape, tile_shape, node_count, data_type = test_shape + + # Setup paths + test_name = f"testSnitchDma_{param_id_dma(test_shape)}_{param_id_dma(doublebuffer)}" + platform = "Snitch" + gen_dir, _, test_name_clean = get_test_paths(f"test_dma_gen/{test_name}", platform, base_dir = deeploy_test_dir) + + # Generate network + if not skipgen: + deployer, test_inputs, test_outputs = setup_dma_deployer("SnitchDma", input_shape, tile_shape, node_count, + data_type, doublebuffer, gen_dir) + generateTestNetwork(deployer, [test_inputs], [test_outputs], gen_dir, _NoVerbosity) + + # Build and run + worker_id = get_worker_id() + if worker_id == "master": + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / "build_master") + else: + build_dir = str(Path(deeploy_test_dir) / f"TEST_{platform.upper()}" / f"build_{worker_id}") + + from testUtils.pytestRunner import DeeployTestConfig + config = DeeployTestConfig( + test_name = test_name_clean, + test_dir = gen_dir, + platform = platform, + simulator = 'gvsoc', + tiling = True, + gen_dir = gen_dir, + build_dir = build_dir, + toolchain = toolchain, + toolchain_install_dir = toolchain_dir, + cmake_args = list(cmake_args) + ["NUM_CORES=9"], + ) + + configure_cmake(config) + build_binary(config) + + if not skipsim: + from testUtils.pytestRunner import run_simulation + result = run_simulation(config) + assert result.success, f"SnitchDma test failed with {result.error_count} errors" + assert result.error_count == 0, f"Found {result.error_count} errors" diff --git a/DeeployTest/test_generic_config.py b/DeeployTest/test_generic_config.py new file mode 100644 index 0000000000..050b8ae0ba --- /dev/null +++ b/DeeployTest/test_generic_config.py @@ -0,0 +1,90 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Generic platform.""" + +KERNEL_TESTS = [ + # FP32 Kernels + "Kernels/FP32/ReLU", + "Kernels/FP32/Softmax/Regular", + "Kernels/FP32/Add/Regular", + "Kernels/FP32/Conv/DW_2D_Bias", + "Kernels/FP32/Conv/DW_2D_NoBias", + "Kernels/FP32/Conv/DW_2D_ZeroValuedBias", + "Kernels/FP32/Conv/Regular_2D_Bias", + "Kernels/FP32/Conv/Regular_2D_NoBias", + "Kernels/FP32/Conv/Regular_2D_ZeroValuedBias", + "Kernels/FP32/Div", + "Kernels/FP32/GEMM/Regular", + "Kernels/FP32/MatMul", + "Kernels/FP32/MaxPool", + "Kernels/FP32/Mul", + "Kernels/FP32/LayerNorm", + "Kernels/FP32/RMSNorm", + "Kernels/FP32/Pow/Scalar", + "Kernels/FP32/Pow/Vector", + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean", + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add", + "Kernels/FP32/ReduceMean/KeepDims/AllAxes", + "Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3", + "Kernels/FP32/ReduceMean/KeepDims/Axes1_3", + "Kernels/FP32/ReduceMean/KeepDims/Axes2_1", + "Kernels/FP32/ReduceMean/KeepDims/Axis0", + "Kernels/FP32/ReduceMean/KeepDims/Axis2", + "Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add", + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean", + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add", + "Kernels/FP32/ReduceMean/NoKeepDims/AllAxes", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1", + "Kernels/FP32/ReduceMean/NoKeepDims/Axis0", + "Kernels/FP32/ReduceMean/NoKeepDims/Axis2", + "Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add", + "Kernels/FP32/Reshape/SkipConnection", + "Kernels/FP32/Sqrt", + "Kernels/FP32/Transpose", + # Integer Kernels + "Kernels/Integer/Softmax/Regular", + "Kernels/Integer/Add/MultIO", + "Kernels/Integer/Add/Regular", + "Kernels/Integer/Conv/DW_1D", + "Kernels/Integer/Conv/Regular_1D", + "Kernels/Integer/Conv/DW_2D", + "Kernels/Integer/Conv/Regular_2D", + "Kernels/Integer/GEMM/Regular", + "Kernels/Integer/MatMul/Add", + "Kernels/Integer/MatMul/Regular", + "Kernels/Integer/MaxPool", + "Kernels/Integer/Pad/Regular_1D", + "Kernels/Integer/Pad/Regular_2D", + "Kernels/Integer/ReduceMean", + "Kernels/Integer/ReduceSum", + "Kernels/Integer/Slice", + # Special test from TinyViT model layers + "Models/TinyViT/5M/Layers/FP32/ReduceMean", + # Mixed Precision / Quantization + "Kernels/Mixed/Dequant", + "Kernels/Mixed/Quant", + "Models/Transformer_DeepQuant", + "Kernels/Integer/Conv/DW_2D_RQ", + "Kernels/Integer/Conv/Regular_2D_RQ", + "Kernels/Integer/MatMul/Regular_RQ", +] + +# Model tests - paths from generic-models job in workflow +MODEL_TESTS = [ + "Models/Autoencoder1D", + "Models/CCT/FP32/CCT_1_16_16_8", + "Models/CCT/FP32/CCT_2_32_32_128_Opset20", + "Models/CCT/Int/ICCT", + "Models/CCT/Int/ICCT_8", + "Models/CCT/Int/ICCT_ITA", + "Models/CCT/Int/ICCT_ITA_8", + "Models/miniMobileNet", + "Models/miniMobileNetv2", + "Models/CNN_Linear1", + "Models/TinyViT/Demo", + "Models/WaveFormer", + "Models/CNN_Linear2", +] diff --git a/DeeployTest/test_mempool_config.py b/DeeployTest/test_mempool_config.py new file mode 100644 index 0000000000..fa0cfd7715 --- /dev/null +++ b/DeeployTest/test_mempool_config.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +""" +Test configuration for MemPool platform. + +This module defines the test lists and default parameters for MemPool platform tests. +""" + +# Default number of threads for MemPool +DEFAULT_NUM_THREADS = 16 + +# Kernel tests (individual operators) +KERNEL_TESTS = [ + "Kernels/Integer/Add/MultIO", + "Kernels/Integer/Add/Regular", + "Kernels/Integer/Conv/DW_1D", + "Kernels/Integer/Conv/Regular_1D", + "Kernels/Integer/Conv/DW_2D", + "Kernels/Integer/Conv/Regular_2D", + "Kernels/Integer/GEMM/Regular", + "Kernels/Integer/MatMul/Add", + "Kernels/Integer/MatMul/Regular", + "Kernels/Integer/MaxPool", + "Kernels/Integer/Pad/Regular_1D", + "Kernels/Integer/Pad/Regular_2D", + "Kernels/Integer/ReduceMean", + "Kernels/Integer/ReduceSum", + "Kernels/Integer/Slice", + "Kernels/Integer/Conv/Regular_2D_RQ", + "Kernels/Integer/Conv/DW_2D_RQ", + "Kernels/Integer/GEMM/Regular_RQPerRow", + "Kernels/Integer/MatMul/Regular_RQ", +] + +# Model tests (full networks) +MODEL_TESTS = [ + "Models/CCT/Int/ICCT", + "Models/CCT/Int/ICCT_8", + "Models/CCT/Int/ICCT_ITA", +] diff --git a/DeeployTest/test_platforms.py b/DeeployTest/test_platforms.py new file mode 100644 index 0000000000..32fece84ec --- /dev/null +++ b/DeeployTest/test_platforms.py @@ -0,0 +1,739 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +import pytest +# Import platform-specific test configurations +from test_chimera_config import KERNEL_TESTS as CHIMERA_KERNEL_TESTS +from test_chimera_config import MODEL_TESTS as CHIMERA_MODEL_TESTS +from test_cortexm_config import KERNEL_TESTS as CORTEXM_KERNEL_TESTS +from test_cortexm_config import MODEL_TESTS as CORTEXM_MODEL_TESTS +from test_generic_config import KERNEL_TESTS as GENERIC_KERNEL_TESTS +from test_generic_config import MODEL_TESTS as GENERIC_MODEL_TESTS +from test_mempool_config import DEFAULT_NUM_THREADS as MEMPOOL_DEFAULT_NUM_THREADS +from test_mempool_config import KERNEL_TESTS as MEMPOOL_KERNEL_TESTS +from test_mempool_config import MODEL_TESTS as MEMPOOL_MODEL_TESTS +from test_siracusa_config import DEFAULT_CORES as SIRACUSA_DEFAULT_CORES +from test_siracusa_config import KERNEL_TESTS as SIRACUSA_KERNEL_TESTS +from test_siracusa_config import MODEL_TESTS as SIRACUSA_MODEL_TESTS +from test_siracusa_neureka_tiled_config import DEFAULT_CORES as NEUREKA_DEFAULT_CORES +from test_siracusa_neureka_tiled_config import L2_DOUBLEBUFFER_KERNELS as NEUREKA_L2_DOUBLEBUFFER_KERNELS +from test_siracusa_neureka_tiled_config import L2_SINGLEBUFFER_KERNELS as NEUREKA_L2_SINGLEBUFFER_KERNELS +from test_siracusa_neureka_tiled_config import L2_SINGLEBUFFER_KERNELS_WMEM as NEUREKA_L2_SINGLEBUFFER_KERNELS_WMEM +from test_siracusa_neureka_tiled_config import L3_DOUBLEBUFFER_MODELS as NEUREKA_L3_DOUBLEBUFFER_MODELS +from test_siracusa_neureka_tiled_config import L3_DOUBLEBUFFER_MODELS_WMEM as NEUREKA_L3_DOUBLEBUFFER_MODELS_WMEM +from test_siracusa_neureka_tiled_config import L3_SINGLEBUFFER_MODELS as NEUREKA_L3_SINGLEBUFFER_MODELS +from test_siracusa_tiled_config import L2_DOUBLEBUFFER_KERNELS, L2_DOUBLEBUFFER_MODELS, L2_SINGLEBUFFER_KERNELS, \ + L2_SINGLEBUFFER_MODELS, L3_DOUBLEBUFFER_MODELS, L3_SINGLEBUFFER_MODELS +from test_snitch_config import DEFAULT_NUM_CORES as SNITCH_DEFAULT_NUM_CORES +from test_snitch_config import KERNEL_TESTS as SNITCH_KERNEL_TESTS +from test_snitch_config import MODEL_TESTS as SNITCH_MODEL_TESTS +from test_snitch_tiled_config import L2_SINGLEBUFFER_KERNELS as SNITCH_L2_SINGLEBUFFER_KERNELS +from test_softhier_config import DEFAULT_NUM_CLUSTERS as SOFTHIER_DEFAULT_NUM_CLUSTERS +from test_softhier_config import KERNEL_TESTS as SOFTHIER_KERNEL_TESTS +from test_softhier_config import MODEL_TESTS as SOFTHIER_MODEL_TESTS +from testUtils.pytestRunner import create_test_config, run_and_assert_test + + +def generate_test_params(test_dict, config_name): + """ + Generate test parameters from a dictionary of test names to L1 values. + + Args: + test_dict: Dictionary mapping test_name -> list of L1 values + config_name: Configuration name for test ID (e.g., "L2-singlebuffer") + + Returns: + List of (test_name, l1_value, config_name) tuples + """ + params = [] + for test_name, l1_values in test_dict.items(): + for l1 in l1_values: + params.append((test_name, l1, config_name)) + return params + + +def param_id(param): + """Generate test ID from parameter tuple.""" + test_name, l1, config = param + return f"{test_name}-{l1}-{config}" + + +### Platform Configuration ### +PLATFORM_CONFIGS = { + "generic": { + "platform": "Generic", + "simulator": "host", + "kernel_tests": GENERIC_KERNEL_TESTS, + "model_tests": GENERIC_MODEL_TESTS, + }, + "cortexm": { + "platform": "QEMU-ARM", + "simulator": "qemu", + "kernel_tests": CORTEXM_KERNEL_TESTS, + "model_tests": CORTEXM_MODEL_TESTS, + }, + "mempool": { + "platform": "MemPool", + "simulator": "banshee", + "kernel_tests": MEMPOOL_KERNEL_TESTS, + "model_tests": MEMPOOL_MODEL_TESTS, + "default_num_threads": MEMPOOL_DEFAULT_NUM_THREADS, + }, + "chimera": { + "platform": "Chimera", + "simulator": "gvsoc", + "kernel_tests": CHIMERA_KERNEL_TESTS, + "model_tests": CHIMERA_MODEL_TESTS, + }, + "softhier": { + "platform": "SoftHier", + "simulator": "gvsoc", + "kernel_tests": SOFTHIER_KERNEL_TESTS, + "model_tests": SOFTHIER_MODEL_TESTS, + "default_num_clusters": SOFTHIER_DEFAULT_NUM_CLUSTERS, + }, + "snitch": { + "platform": "Snitch", + "simulator": "gvsoc", + "kernel_tests": SNITCH_KERNEL_TESTS, + "model_tests": SNITCH_MODEL_TESTS, + "default_num_cores": SNITCH_DEFAULT_NUM_CORES, + }, +} + +### Markers summary ### +# Platform markers: +# generic: tests from the generic platform +# cortexm: tests from the cortex-m (QEMU-ARM) platform +# mempool: tests from the MemPool platform +# chimera: tests from the Chimera platform +# softhier: tests from the SoftHier platform +# snitch: tests from the Snitch platform (untiled) +# snitch_tiled: tests from the Snitch platform (tiled) +# siracusa: tests from the Siracusa platform (untiled) +# siracusa_tiled: tests from the Siracusa platform (tiled) +# siracusa_neureka_tiled: tests from the Siracusa + Neureka platform (tiled) +# Test type markers: +# kernels: single kernel (or single layer) tests +# models: full model (multiple layer) tests +# Configuration markers (tiled platforms): +# singlebuffer: single-buffer tests +# doublebuffer: double-buffer tests +# l2: L2 default memory level +# l3: L3 default memory level +# wmem: with Neureka weight memory enabled + + +@pytest.mark.generic +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", GENERIC_KERNEL_TESTS, ids = GENERIC_KERNEL_TESTS) +def test_generic_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["generic"] + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.generic +@pytest.mark.models +@pytest.mark.parametrize("test_name", GENERIC_MODEL_TESTS, ids = GENERIC_MODEL_TESTS) +def test_generic_models(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["generic"] + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.cortexm +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", CORTEXM_KERNEL_TESTS, ids = CORTEXM_KERNEL_TESTS) +def test_cortexm_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["cortexm"] + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.cortexm +@pytest.mark.models +@pytest.mark.parametrize("test_name", CORTEXM_MODEL_TESTS, ids = CORTEXM_MODEL_TESTS) +def test_cortexm_models(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["cortexm"] + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.mempool +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", MEMPOOL_KERNEL_TESTS, ids = MEMPOOL_KERNEL_TESTS) +def test_mempool_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["mempool"] + + # Add MemPool-specific CMake args for number of threads + mempool_cmake_args = cmake_args + [f"num_threads={platform_config['default_num_threads']}"] + + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = mempool_cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.mempool +@pytest.mark.models +@pytest.mark.parametrize("test_name", MEMPOOL_MODEL_TESTS, ids = MEMPOOL_MODEL_TESTS) +def test_mempool_models(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["mempool"] + + # Add MemPool-specific CMake args for number of threads + mempool_cmake_args = cmake_args + [f"num_threads={platform_config['default_num_threads']}"] + + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = mempool_cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", SIRACUSA_KERNEL_TESTS, ids = SIRACUSA_KERNEL_TESTS) +def test_siracusa_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + cores = SIRACUSA_DEFAULT_CORES, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa +@pytest.mark.models +@pytest.mark.parametrize("test_name", SIRACUSA_MODEL_TESTS, ids = SIRACUSA_MODEL_TESTS) +def test_siracusa_models(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + cores = SIRACUSA_DEFAULT_CORES, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.kernels +@pytest.mark.singlebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L2_SINGLEBUFFER_KERNELS, "L2-singlebuffer"), + ids = param_id, +) +def test_siracusa_tiled_kernels_l2_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.kernels +@pytest.mark.doublebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L2_DOUBLEBUFFER_KERNELS, "L2-doublebuffer"), + ids = param_id, +) +def test_siracusa_tiled_kernels_l2_doublebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = True, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.models +@pytest.mark.singlebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L2_SINGLEBUFFER_MODELS, "L2-singlebuffer"), + ids = param_id, +) +def test_siracusa_tiled_models_l2_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.models +@pytest.mark.doublebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L2_DOUBLEBUFFER_MODELS, "L2-doublebuffer"), + ids = param_id, +) +def test_siracusa_tiled_models_l2_doublebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = True, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.models +@pytest.mark.singlebuffer +@pytest.mark.l3 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L3_SINGLEBUFFER_MODELS, "L3-singlebuffer"), + ids = param_id, +) +def test_siracusa_tiled_models_l3_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L3", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_tiled +@pytest.mark.models +@pytest.mark.doublebuffer +@pytest.mark.l3 +@pytest.mark.parametrize( + "test_params", + generate_test_params(L3_DOUBLEBUFFER_MODELS, "L3-doublebuffer"), + ids = param_id, +) +def test_siracusa_tiled_models_l3_doublebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = SIRACUSA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L3", + double_buffer = True, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.chimera +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", CHIMERA_KERNEL_TESTS, ids = CHIMERA_KERNEL_TESTS) +def test_chimera_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["chimera"] + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.softhier +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", SOFTHIER_KERNEL_TESTS, ids = SOFTHIER_KERNEL_TESTS) +def test_softhier_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["softhier"] + + # Add SoftHier-specific CMake args for number of clusters + softhier_cmake_args = cmake_args + [f"num_clusters={platform_config['default_num_clusters']}"] + + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = softhier_cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.snitch +@pytest.mark.kernels +@pytest.mark.parametrize("test_name", SNITCH_KERNEL_TESTS, ids = SNITCH_KERNEL_TESTS) +def test_snitch_kernels(test_name, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, skipgen, skipsim) -> None: + platform_config = PLATFORM_CONFIGS["snitch"] + + # Add Snitch-specific CMake args for number of cores + snitch_cmake_args = cmake_args + [f"NUM_CORES={platform_config['default_num_cores']}"] + + config = create_test_config( + test_name = test_name, + platform = platform_config["platform"], + simulator = platform_config["simulator"], + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = snitch_cmake_args, + tiling = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.snitch_tiled +@pytest.mark.kernels +@pytest.mark.singlebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(SNITCH_L2_SINGLEBUFFER_KERNELS, "L2-singlebuffer"), + ids = param_id, +) +def test_snitch_tiled_kernels_l2_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, cmake_args, + skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + + # Add Snitch-specific CMake args + snitch_cmake_args = cmake_args + [f"NUM_CORES={SNITCH_DEFAULT_NUM_CORES}"] + + config = create_test_config( + test_name = test_name, + platform = "Snitch", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = snitch_cmake_args, + tiling = True, + cores = SNITCH_DEFAULT_NUM_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.kernels +@pytest.mark.singlebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L2_SINGLEBUFFER_KERNELS, "L2-singlebuffer"), + ids = param_id, +) +def test_siracusa_neureka_tiled_kernels_l2_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.kernels +@pytest.mark.doublebuffer +@pytest.mark.l2 +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L2_DOUBLEBUFFER_KERNELS, "L2-doublebuffer"), + ids = param_id, +) +def test_siracusa_neureka_tiled_kernels_l2_doublebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = True, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.models +@pytest.mark.singlebuffer +@pytest.mark.l3 +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L3_SINGLEBUFFER_MODELS, "L3-singlebuffer"), + ids = param_id, +) +def test_siracusa_neureka_tiled_models_l3_singlebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L3", + double_buffer = False, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.models +@pytest.mark.doublebuffer +@pytest.mark.l3 +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L3_DOUBLEBUFFER_MODELS, "L3-doublebuffer"), + ids = param_id, +) +def test_siracusa_neureka_tiled_models_l3_doublebuffer(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L3", + double_buffer = True, + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.kernels +@pytest.mark.singlebuffer +@pytest.mark.l2 +@pytest.mark.wmem +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L2_SINGLEBUFFER_KERNELS_WMEM, "L2-singlebuffer-wmem"), + ids = param_id, +) +def test_siracusa_neureka_tiled_kernels_l2_singlebuffer_wmem(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L2", + double_buffer = False, + gen_args = ["--neureka-wmem"], + ) + run_and_assert_test(test_name, config, skipgen, skipsim) + + +@pytest.mark.siracusa_neureka_tiled +@pytest.mark.models +@pytest.mark.doublebuffer +@pytest.mark.l3 +@pytest.mark.wmem +@pytest.mark.parametrize( + "test_params", + generate_test_params(NEUREKA_L3_DOUBLEBUFFER_MODELS_WMEM, "L3-doublebuffer-wmem"), + ids = param_id, +) +def test_siracusa_neureka_tiled_models_l3_doublebuffer_wmem(test_params, deeploy_test_dir, toolchain, toolchain_dir, + cmake_args, skipgen, skipsim) -> None: + test_name, l1, config_name = test_params + config = create_test_config( + test_name = test_name, + platform = "Siracusa_w_neureka", + simulator = "gvsoc", + deeploy_test_dir = deeploy_test_dir, + toolchain = toolchain, + toolchain_dir = toolchain_dir, + cmake_args = cmake_args, + tiling = True, + cores = NEUREKA_DEFAULT_CORES, + l1 = l1, + default_mem_level = "L3", + double_buffer = True, + gen_args = ["--neureka-wmem"], + ) + run_and_assert_test(test_name, config, skipgen, skipsim) diff --git a/DeeployTest/test_siracusa_config.py b/DeeployTest/test_siracusa_config.py new file mode 100644 index 0000000000..0a77d714e8 --- /dev/null +++ b/DeeployTest/test_siracusa_config.py @@ -0,0 +1,80 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +PLATFORM_NAME = "Siracusa" +SIMULATOR = "gvsoc" +DEFAULT_CORES = 8 + +KERNEL_TESTS = [ + "Kernels/FP32/ReLU", + "Kernels/FP32/Softmax/CrossEntropy", + "Kernels/FP32/Softmax/CrossEntropyGrad", + "Kernels/FP32/Softmax/Grad", + "Kernels/FP32/Softmax/Regular", + "Kernels/FP32/Add/Regular", + "Kernels/FP32/Conv/DW_2D_Bias", + "Kernels/FP32/Conv/DW_2D_NoBias", + "Kernels/FP32/Conv/DW_2D_ZeroValuedBias", + "Kernels/FP32/Conv/Regular_2D_Bias", + "Kernels/FP32/Conv/Regular_2D_NoBias", + "Kernels/FP32/Conv/Regular_2D_ZeroValuedBias", + "Kernels/FP32/GEMM/Regular", + "Kernels/FP32/MatMul", + "Kernels/FP32/MaxPool", + "Kernels/FP32/Mul", + "Kernels/FP32/LayerNorm", + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean", + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add", + "Kernels/FP32/ReduceMean/KeepDims/AllAxes", + "Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3", + "Kernels/FP32/ReduceMean/KeepDims/Axes1_3", + "Kernels/FP32/ReduceMean/KeepDims/Axes2_1", + "Kernels/FP32/ReduceMean/KeepDims/Axis0", + "Kernels/FP32/ReduceMean/KeepDims/Axis2", + "Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add", + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean", + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add", + "Kernels/FP32/ReduceMean/NoKeepDims/AllAxes", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3", + "Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1", + "Kernels/FP32/ReduceMean/NoKeepDims/Axis0", + "Kernels/FP32/ReduceMean/NoKeepDims/Axis2", + "Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add", + "Kernels/FP32/ReduceSum", + "Kernels/FP32/Reshape/SkipConnection", + "Kernels/FP32/Transpose", + "Kernels/Integer/Hardswish/Regular", + "Kernels/Integer/Softmax/Regular", + "Kernels/Integer/Add/MultIO", + "Kernels/Integer/Add/Regular", + "Kernels/Integer/Concat", + "Kernels/Integer/MatMul/Add", + "Kernels/Integer/MatMul/Regular", + "Kernels/Integer/Pad/Regular_1D", + "Kernels/Integer/Pad/Regular_2D", + "Kernels/Integer/RMSNorm", + "Models/TinyViT/5M/Layers/FP32/ReduceMean", + "Others/Backtracking", + "Kernels/Mixed/Dequant", + "Kernels/Mixed/Quant", + "Models/Transformer_DeepQuant", + "Kernels/Integer/Conv/Regular_2D_RQ", + "Kernels/Integer/Conv/DW_2D_RQ", + "Kernels/Integer/Hardswish/Regular_RQ", + "Kernels/Integer/TrueIntegerDiv", +] + +MODEL_TESTS = [ + "Kernels/Integer/Attention", + "Models/CCT/FP32/CCT_1_16_16_8", + "Models/CCT/FP32/CCT_2_32_32_128_Opset20", + "Models/miniMobileNet", + "Models/miniMobileNetv2", + "Models/MLPerf/KeywordSpotting", + "Models/MLPerf/ImageClassification", + "Models/MLPerf/AnomalyDetection", + "Models/TinyViT/Demo", + "Models/CNN_Linear2", +] diff --git a/DeeployTest/test_siracusa_neureka_tiled_config.py b/DeeployTest/test_siracusa_neureka_tiled_config.py new file mode 100644 index 0000000000..68bd3dd96e --- /dev/null +++ b/DeeployTest/test_siracusa_neureka_tiled_config.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Siracusa platform with Neureka accelerator (tiled).""" + +# Siracusa + Neureka platform with tiling support +# Default configuration: 8 cores, gvsoc simulator + +DEFAULT_CORES = 8 + +# L2 single-buffer kernel tests +# Format: dict of {test_name: [L1_sizes]} +L2_SINGLEBUFFER_KERNELS = { + "Kernels/Integer/GEMM/Regular_RQPerColumn": [16000], + "Kernels/Integer/Conv/PW_2D": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ": [32000], +} + +# L2 double-buffer kernel tests +L2_DOUBLEBUFFER_KERNELS = { + "Kernels/Integer/GEMM/Regular_RQPerColumn": [16000], + "Kernels/Integer/Conv/PW_2D": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ": [32000], +} + +# L3 single-buffer model tests +# Format: dict of {test_name: [L1_sizes]} +L3_SINGLEBUFFER_MODELS = { + "Models/miniMobileNet": [2000], + "Kernels/Integer/Attention": [2500], + "Models/Transformer": [15000], + "Models/microLlama/microLlama1": [10000], +} + +# L3 double-buffer model tests +L3_DOUBLEBUFFER_MODELS = { + "Models/miniMobileNet": [2000], + "Kernels/Integer/Attention": [5000], + "Models/Transformer": [30000], +} + +# L2 single-buffer kernel tests with weight memory (neureka-wmem) +L2_SINGLEBUFFER_KERNELS_WMEM = { + "Kernels/Integer/GEMM/Regular_RQPerColumn": [16000], + "Kernels/Integer/Conv/PW_2D": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Regular_RQ": [32000], + "Kernels/Integer/Conv/PW_2D_RQ/Unsigned_RQ": [32000], +} + +# L3 double-buffer model tests with weight memory (neureka-wmem) +L3_DOUBLEBUFFER_MODELS_WMEM = { + "Models/miniMobileNet": [2000], + "Kernels/Integer/Attention": [3500], + "Models/microLlama/microLlama1": [10000], +} diff --git a/DeeployTest/test_siracusa_tiled_config.py b/DeeployTest/test_siracusa_tiled_config.py new file mode 100644 index 0000000000..1c0bb0315c --- /dev/null +++ b/DeeployTest/test_siracusa_tiled_config.py @@ -0,0 +1,158 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +PLATFORM_NAME = "Siracusa" +SIMULATOR = "gvsoc" +DEFAULT_CORES = 8 +DEFAULT_L2 = 1024000 +DEFAULT_MEM_ALLOC_STRATEGY = "MiniMalloc" +DEFAULT_SEARCH_STRATEGY = "random-max" + +L2_SINGLEBUFFER_KERNELS = { + "Kernels/FP32/ReLU": [2000], + "Kernels/FP32/Softmax/Regular": [4000], + "Kernels/FP32/Add/Large": [220000], + "Kernels/FP32/Conv/DW_2D_Bias": [7200], + "Kernels/FP32/Conv/DW_2D_NoBias": [7200], + "Kernels/FP32/Conv/DW_2D_ZeroValuedBias": [7200], + "Kernels/FP32/Conv/Regular_2D_Bias": [6600], + "Kernels/FP32/Conv/Regular_2D_NoBias": [1600], + "Kernels/FP32/Conv/Regular_2D_ZeroValuedBias": [6600], + "Kernels/FP32/GEMM/Regular": [8000], + "Kernels/FP32/MatMul": [2000], + "Kernels/FP32/MaxPool": [2000], + "Kernels/FP32/Mul": [2000], + "Kernels/FP32/LayerNorm": [2000], + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean": [8000], + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/KeepDims/AllAxes": [50000], + "Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3": [50000], + "Kernels/FP32/ReduceMean/KeepDims/Axes1_3": [5000, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axes2_1": [6200, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axis0": [8400, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axis2": [8400, 50000], + "Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/AllAxes": [50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3": [50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3": [5000, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1": [6200, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axis0": [8400, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axis2": [8400, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add": [8000], + "Kernels/FP32/Reshape/SkipConnection": [1400], + "Kernels/FP32/Transpose": [2000], + "Kernels/Integer/Hardswish/Regular": [750], + "Kernels/Integer/Softmax/Regular": [800, 500, 300], + "Kernels/Integer/Concat": [32000, 16000, 8000], + "Kernels/Integer/MatMul/Batch": [20000], + "Kernels/Integer/MatMul/Regular": [64000, 32000, 16000], + "Kernels/Integer/RMSNorm": [2048, 1024, 512], + "Kernels/Integer/Conv/Regular_2D_RQ": [8000, 6000, 4000], + "Kernels/Integer/Conv/DW_2D_RQ": [2561], + "Kernels/Integer/Conv/StriddedPadded_2D_RQ": [600], + "Kernels/Integer/GEMM/Batch_RQ": [20000], + "Kernels/Integer/Hardswish/Regular_RQ": [750], +} + +L2_DOUBLEBUFFER_KERNELS = { + "Kernels/FP32/ReLU": [20], + "Kernels/FP32/Softmax/Regular": [8000], + "Kernels/FP32/Conv/DW_2D_Bias": [10000], + "Kernels/FP32/Conv/DW_2D_NoBias": [9800], + "Kernels/FP32/Conv/DW_2D_ZeroValuedBias": [9800], + "Kernels/FP32/Conv/Regular_2D_Bias": [8800], + "Kernels/FP32/Conv/Regular_2D_NoBias": [2000], + "Kernels/FP32/Conv/Regular_2D_ZeroValuedBias": [8800], + "Kernels/FP32/GEMM/Regular": [8000], + "Kernels/FP32/MatMul": [5000], + "Kernels/FP32/MaxPool": [5000], + "Kernels/FP32/Mul": [2000], + "Kernels/FP32/LayerNorm": [2000], + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean": [8000], + "Kernels/FP32/ReduceMean/KeepDims/Add_ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/KeepDims/AllAxes": [100000], + "Kernels/FP32/ReduceMean/KeepDims/Axes1_2_3": [100000], + "Kernels/FP32/ReduceMean/KeepDims/Axes1_3": [10000, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axes2_1": [13000, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axis0": [17000, 50000], + "Kernels/FP32/ReduceMean/KeepDims/Axis2": [17000, 50000], + "Kernels/FP32/ReduceMean/KeepDims/ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/Add_ReduceMean_Add": [8000], + "Kernels/FP32/ReduceMean/NoKeepDims/AllAxes": [100000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_2_3": [100000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes1_3": [10000, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axes2_1": [13000, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axis0": [17000, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/Axis2": [17000, 50000], + "Kernels/FP32/ReduceMean/NoKeepDims/ReduceMean_Add": [8000], + "Kernels/FP32/Reshape/SkipConnection": [2600], + "Kernels/FP32/Transpose": [2000], + "Kernels/Integer/Hardswish/Regular": [750], + "Kernels/Integer/Softmax/Regular": [1600, 1000, 600], + "Kernels/Integer/Concat": [64000, 32000, 16000], + "Kernels/Integer/MatMul/Regular": [64000, 32000, 16000], + "Kernels/Integer/RMSNorm": [4096, 2048, 1024], + "Kernels/Integer/Conv/Regular_2D_RQ": [8000, 6000, 5000], + "Kernels/Integer/Conv/DW_2D_RQ": [5121], + "Kernels/Integer/Hardswish/Regular_RQ": [800], +} + +L2_SINGLEBUFFER_MODELS = { + "Models/CNN_Linear2": [45000, 30000, 15000], + "Models/miniMobileNet": [60000, 12000, 6000, 3000], + "Models/miniMobileNetv2": [60000, 16000, 12000, 8000], + "Kernels/Integer/Attention": [60000, 10000, 5000], + "Models/microLlama/microLlama1": [60000, 10000, 5000], + "Models/microLlama/microLlama8": [60000, 10000, 5000], + "Models/microLlama/microLlama8_parallel": [60000, 10000, 5000], + "Models/MLPerf/KeywordSpotting": [64000], + "Models/MLPerf/ImageClassification": [64000], + "Models/MLPerf/AnomalyDetection": [64000], + "Models/CCT/FP32/CCT_1_16_16_8": [64000], + "Models/TinyViT/Demo": [4000], +} + +L2_DOUBLEBUFFER_MODELS = { + "Models/CNN_Linear2": [60000, 45000, 30000], + "Models/miniMobileNet": [60000, 24000, 12000, 6000], + "Models/miniMobileNetv2": [60000, 32000, 24000, 16000], + "Kernels/Integer/Attention": [60000, 20000, 10000, 5000], + "Models/microLlama/microLlama1": [60000, 20000, 10000], + "Models/microLlama/microLlama8": [60000, 20000, 10000], + "Models/microLlama/microLlama8_parallel": [60000, 20000, 10000], + "Models/MLPerf/KeywordSpotting": [128000], + "Models/MLPerf/ImageClassification": [128000], + "Models/MLPerf/AnomalyDetection": [128000], + "Models/CCT/FP32/CCT_1_16_16_8": [128000], + "Models/TinyViT/Demo": [8000], +} + +L3_SINGLEBUFFER_MODELS = { + "Models/CNN_Linear2": [45000, 30000, 16000], + "Models/miniMobileNet": [60000, 12000, 6000], + "Models/miniMobileNetv2": [60000, 16000, 12000, 8000], + "Kernels/Integer/Attention": [60000, 10000, 5000, 2500], + "Models/Transformer": [60000, 30000, 15000], + "Models/microLlama/microLlama1": [60000, 10000, 5000], + "Models/CCT/FP32/CCT_2_32_32_128": [128000], + "Models/CCT_Train/CCT2_FT2": [128000], + "Models/TinyViT/Demo": [4000], +} + +L3_DOUBLEBUFFER_MODELS = { + "Models/CNN_Linear2": [60000, 45000, 30000], + "Models/miniMobileNet": [60000, 24000, 12000, 6000], + "Models/miniMobileNetv2": [60000, 32000, 24000, 16000], + "Kernels/Integer/Attention": [60000, 20000, 10000, 5000], + "Models/Transformer": [60000, 30000, 15000], + "Models/microLlama/microLlama1": [60000, 20000, 10000], + "Models/microLlama/microLlama8": [60000, 20000, 10000], + "Models/microLlama/microLlama8_parallel": [60000, 20000, 10000], + "Models/CCT/FP32/CCT_2_32_32_128": [128000], + "Models/CCT_Train/CCT2_FT2": [128000], + "Models/TinyViT/Demo": [4000], +} diff --git a/DeeployTest/test_snitch_config.py b/DeeployTest/test_snitch_config.py new file mode 100644 index 0000000000..f51b2ede23 --- /dev/null +++ b/DeeployTest/test_snitch_config.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Snitch platform.""" + +# Snitch platform supports gvsoc, banshee, vsim simulators +# Default configuration: 9 cores + +DEFAULT_NUM_CORES = 9 + +KERNEL_TESTS = [ + "Kernels/FP32/Softmax/Regular", + "Kernels/Integer/Add/Large", + "Kernels/Integer/Add/Regular", + "Kernels/Integer/Softmax/Large", + "Kernels/Integer/Softmax/Regular", + "Kernels/Integer/MatMul/Regular", + "Kernels/Integer/iNoNorm", + "Kernels/Integer/GEMM/Regular_RQPerRow", + "Kernels/Integer/Add/Regular_RQ", + "Kernels/Integer/GEMM/TransB_RQ", +] + +MODEL_TESTS = [] diff --git a/DeeployTest/test_snitch_tiled_config.py b/DeeployTest/test_snitch_tiled_config.py new file mode 100644 index 0000000000..3f81239fce --- /dev/null +++ b/DeeployTest/test_snitch_tiled_config.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for Snitch platform (tiled).""" + +# Snitch tiled platform supports gvsoc, banshee, vsim simulators +# Default configuration: 9 cores, L2 default memory level + +DEFAULT_NUM_CORES = 9 + +# L2 single-buffer tests with different L1 sizes +# Format: {test_name: [L1_sizes]} +L2_SINGLEBUFFER_KERNELS = { + "Kernels/Integer/Add/Large": [5000, 10000], + "Kernels/Integer/Softmax/Large": [5000, 10000], + "Kernels/FP32/Softmax/Regular": [2000, 5000, 10000], + "Kernels/FP32/GEMM/Regular": [2000, 5000, 10000], + "Kernels/FP32/GEMM/TransB": [2000, 5000, 10000], + "Kernels/Integer/iNoNorm": [5000, 10000], + "Kernels/Integer/Add/Regular_RQ": [5000, 10000], + "Kernels/Integer/GEMM/Regular_RQPerRow": [2000, 5000], +} + +L2_SINGLEBUFFER_MODELS = {} + +# Currently no double-buffer configurations in CI +L2_DOUBLEBUFFER_KERNELS = {} +L2_DOUBLEBUFFER_MODELS = {} diff --git a/DeeployTest/test_softhier_config.py b/DeeployTest/test_softhier_config.py new file mode 100644 index 0000000000..18d2f61c7d --- /dev/null +++ b/DeeployTest/test_softhier_config.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +"""Test configuration for SoftHier platform.""" + +# SoftHier platform uses gvsoc simulator +# Default configuration: 1 cluster + +DEFAULT_NUM_CLUSTERS = 1 + +KERNEL_TESTS = [ + "Kernels/Integer/Add/Regular", +] + +MODEL_TESTS = [] diff --git a/pyproject.toml b/pyproject.toml index d807bddab4..0dda1a55b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,10 +26,11 @@ dependencies = [ 'mako', 'argparse', 'toml', -'pytest', 'ortools', 'plotly', -'coloredlogs' +'coloredlogs', +'pytest', +'pytest-xdist', ] [project.urls] diff --git a/scripts/generate_test_matrix.py b/scripts/generate_test_matrix.py new file mode 100755 index 0000000000..c25fe534f0 --- /dev/null +++ b/scripts/generate_test_matrix.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 +""" +Generate GitHub Actions test matrix from Python test configuration. + +This script reads test configurations from DeeployTest config files and outputs +JSON arrays suitable for GitHub Actions matrix strategies. +""" + +import json +import sys +from pathlib import Path + +# Add DeeployTest to path to import config +sys.path.insert(0, str(Path(__file__).parent.parent / "DeeployTest")) + +from test_siracusa_tiled_config import L2_DOUBLEBUFFER_MODELS, L2_SINGLEBUFFER_MODELS, L3_DOUBLEBUFFER_MODELS, \ + L3_SINGLEBUFFER_MODELS + + +def main(): + if len(sys.argv) != 2: + print("Usage: generate_test_matrix.py ", file = sys.stderr) + print("config-key must be one of:", file = sys.stderr) + print(" l2-singlebuffer-models", file = sys.stderr) + print(" l2-doublebuffer-models", file = sys.stderr) + print(" l3-singlebuffer-models", file = sys.stderr) + print(" l3-doublebuffer-models", file = sys.stderr) + sys.exit(1) + + config_key = sys.argv[1] + + # Map config keys to Python dictionaries + config_map = { + "l2-singlebuffer-models": L2_SINGLEBUFFER_MODELS, + "l2-doublebuffer-models": L2_DOUBLEBUFFER_MODELS, + "l3-singlebuffer-models": L3_SINGLEBUFFER_MODELS, + "l3-doublebuffer-models": L3_DOUBLEBUFFER_MODELS, + } + + if config_key not in config_map: + print(f"Error: Unknown config-key '{config_key}'", file = sys.stderr) + sys.exit(1) + + # Extract test names from the dictionary keys + test_dict = config_map[config_key] + test_names = list(test_dict.keys()) + + # Output as JSON array + print(json.dumps(test_names)) + + +if __name__ == "__main__": + main() diff --git a/toolchain/banshee.patch b/toolchain/banshee.patch index 6e982afcb8..51fdc946ce 100644 --- a/toolchain/banshee.patch +++ b/toolchain/banshee.patch @@ -1,10 +1,10 @@ diff --git a/Cargo.toml b/Cargo.toml -index d406357..eb5ce8e 100644 +index d406357..f14c0f7 100644 --- a/Cargo.toml +++ b/Cargo.toml -@@ -11,30 +11,32 @@ edition = "2018" +@@ -11,30 +11,34 @@ edition = "2018" build = "build/build.rs" - + [dependencies] -anyhow = "1" -binread = "2.2.0" @@ -25,35 +25,40 @@ index d406357..eb5ce8e 100644 flexfloat = { path = "flexfloat" } -itertools = "0.9" -llvm-sys = "120" -+itertools = "=0.9" -+llvm-sys = "150" - log = { version = "0.4", features = ["release_max_level_info"] } +-log = { version = "0.4", features = ["release_max_level_info"] } -pest = "2.1.3" -pest_derive = "2.1.0" -ndarray = "0.13" -pretty_env_logger = "0.4" -+pest = "=2.1.3" -+pest_derive = "=2.1.0" -+ndarray = "=0.13" -+pretty_env_logger = "=0.4" - regex = "~1.9.6" +-regex = "~1.9.6" -rev_slice = "0.1.5" -+rev_slice = "=0.1.5" - serde = { version = "1.0.123", features = ["derive"] } +-serde = { version = "1.0.123", features = ["derive"] } -serde_json = "1.0.63" -serde_yaml = "0.8" -termion = "2.0.3" -thiserror = "1.0.21" -to-binary = "0.4.0" ++itertools = "=0.9" ++llvm-sys = "=150" ++log = { version = "=0.4.17", features = ["release_max_level_info"] } ++pest = "=2.1.3" ++pest_derive = "=2.1.0" ++ndarray = "=0.13" ++pretty_env_logger = "=0.4" ++regex = "=1.9.6" ++rev_slice = "=0.1.5" ++serde = { version = "=1.0.123", features = ["derive"] } +serde_json = "=1.0.63" +serde_yaml = "=0.8" +termion = "=2.0.3" +thiserror = "=1.0.21" +to-binary = "=0.4.0" -+libc = "0.2" - ++libc = "=0.2" ++quote = "=1.0.41" + [build-dependencies] cc = "1.0" ++cmake = "=0.1.50" diff --git a/build/runtime.rs b/build/runtime.rs index 04f80b8..c03f248 100644 --- a/build/runtime.rs @@ -69,16 +74,16 @@ index 04f80b8..c03f248 100644 .status() .unwrap(); diff --git a/src/engine.rs b/src/engine.rs -index 216996b..e5abe38 100644 +index f32a539..a79a708 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -281,7 +281,6 @@ impl Engine { - + LLVMPassManagerBuilderPopulateFunctionPassManager(builder, func_passes); LLVMAddAnalysisPasses(tm, module_passes); - LLVMPassManagerBuilderPopulateLTOPassManager(builder, module_passes, 0, 1); LLVMPassManagerBuilderPopulateModulePassManager(builder, module_passes); - + // Create and run the function pass manager. diff --git a/src/tran.rs b/src/tran.rs index 1054744..ae5ae78 100644 @@ -90,9 +95,9 @@ index 1054744..ae5ae78 100644 }; +use libc; extern crate flexfloat; - + -static NONAME: &'static i8 = unsafe { std::mem::transmute("\0".as_ptr()) }; +static NONAME: &'static libc::c_char = unsafe { std::mem::transmute("\0".as_ptr()) }; - + /// Base address of the stream semantic regsiters static SSR_BASE: u64 = 0x204800;