From 2b4a75545cd78b6a7d5b148b546a2e9c9a64b282 Mon Sep 17 00:00:00 2001 From: Philip Wiese Date: Wed, 9 Jul 2025 15:10:55 +0200 Subject: [PATCH 01/28] Prepare Post v0.2.0 Release (#104) Setup v0.2.1 release --- CHANGELOG.md | 18 +++++++++++++++++- pyproject.toml | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b3b3892d..0a5bd1a701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,23 @@ # Changelog This file contains the changelog for the Deeploy project. The changelog is divided into sections based on the version of the project. Each section contains a list of pull requests, features, changes, fixes, and removals that were made in that version. -## Release v0.2.0 (2025-07-09) +## Unreleased (Planned Release Target: v0.2.1) +### List of Pull Requests +- Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) + +### Added +- + +### Changed +- + +### Fixed +- + +### Removed +- + +## Release v0.2.0 (2025-07-08) [#103](https://github.com/pulp-platform/Deeploy/pull/103) This release containing major architectural changes, new platform support, enhanced simulation workflows, floating-point kernel support, training infrastructure for CCT models, memory allocation strategies, and documentation improvements. ### List of Pull Requests diff --git a/pyproject.toml b/pyproject.toml index 752603f21b..758bbae9ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "PULP-Deeploy" -version = '0.2.0' +version = '0.2.1' description = "Deeploy - DNN Compiler for Heterogeneous SoCs" authors = [ { name="Victor Jung", email="jungvi@iis.ee.ethz.ch" }, From 9ef3217e3196eac4298a0b3f2a02dc7cbbfce3ed Mon Sep 17 00:00:00 2001 From: Philip Wiese Date: Wed, 30 Jul 2025 15:22:57 +0200 Subject: [PATCH 02/28] Use Docker digests instead of arch-specific tags (#106) * Update action versions and fix missing id * Avoid platform-specific image tags by using digests in Docker manifest * Replaces per-architecture tags (e.g., *-amd64, *-arm64) with direct digest references when creating the multi-arch Docker manifest. This reduces tag clutter in the registry. * Update Changelog --- .github/workflows/BuildDockerDeeploy.yml | 32 +++++++++++++------- .github/workflows/BuildDockerToolchain.yml | 34 +++++++++++++++------- CHANGELOG.md | 7 +++-- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/.github/workflows/BuildDockerDeeploy.yml b/.github/workflows/BuildDockerDeeploy.yml index 2b2bf5d169..34bd55d8ee 100644 --- a/.github/workflows/BuildDockerDeeploy.yml +++ b/.github/workflows/BuildDockerDeeploy.yml @@ -36,6 +36,9 @@ jobs: name: Build Deploy Image needs: [ prepare ] runs-on: ${{ matrix.runner }} + outputs: + digest-amd64: ${{ steps.digest.outputs.digest-amd64 }} + digest-arm64: ${{ steps.digest.outputs.digest-arm64 }} strategy: fail-fast: false matrix: @@ -57,17 +60,18 @@ jobs: haskell: true large-packages: true - - uses: docker/setup-buildx-action@v1 + - uses: docker/setup-buildx-action@v3 - name: GHCR Log-in - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build Cache for Docker - uses: actions/cache@v3 + id: cache + uses: actions/cache@v4 with: path: var-ccache key: ${{ runner.os }}-${{ matrix.platform }}-build-cache-deeploy @@ -88,6 +92,7 @@ jobs: OWNER: '${{ github.repository_owner }}' - name: Build and push final deploy image + id: build uses: docker/build-push-action@v6 with: platforms: linux/${{ matrix.platform }} @@ -98,9 +103,11 @@ jobs: push: true build-args: | BASE_IMAGE=${{ github.event.inputs.docker_image_toolchain }} - tags: | - ghcr.io/${{ env.OWNER_LC }}/deeploy:latest-${{ matrix.platform }} - ghcr.io/${{ env.OWNER_LC }}/deeploy:${{ needs.prepare.outputs.docker_tag }}-${{ matrix.platform }} + outputs: type=image,name=ghcr.io/${{ env.OWNER_LC }}/deeploy,annotation-index=true,name-canonical=true,push=true + + - name: Extract image digest + id: digest + run: echo "digest-${{ matrix.platform }}=${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT merge-deeploy-images: name: Merge Deeploy Images @@ -108,7 +115,7 @@ jobs: needs: [ prepare, build-deeploy ] steps: - name: GHCR Log-in - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} @@ -120,8 +127,13 @@ jobs: env: OWNER: '${{ github.repository_owner }}' - - uses: Noelware/docker-manifest-action@v1 + - name: Merge Deeploy Images + uses: Noelware/docker-manifest-action@v1 with: - inputs: ghcr.io/${{ env.OWNER_LC }}/deeploy:latest-amd64,ghcr.io/${{ env.OWNER_LC }}/deeploy:latest-arm64 - tags: ghcr.io/${{ env.OWNER_LC }}/deeploy:latest,ghcr.io/${{ env.OWNER_LC }}/deeploy:${{ needs.prepare.outputs.docker_tag }} + inputs: | + ghcr.io/${{ env.OWNER_LC }}/deeploy@${{ needs.build-deeploy.outputs.digest-amd64 }}, + ghcr.io/${{ env.OWNER_LC }}/deeploy@${{ needs.build-deeploy.outputs.digest-arm64 }} + tags: | + ghcr.io/${{ env.OWNER_LC }}/deeploy:latest, + ghcr.io/${{ env.OWNER_LC }}/deeploy:${{ needs.prepare.outputs.docker_tag }} push: true \ No newline at end of file diff --git a/.github/workflows/BuildDockerToolchain.yml b/.github/workflows/BuildDockerToolchain.yml index 7b128948d1..03f9226288 100644 --- a/.github/workflows/BuildDockerToolchain.yml +++ b/.github/workflows/BuildDockerToolchain.yml @@ -31,6 +31,9 @@ jobs: name: Build Deeploy Toolchain Image needs: [ prepare ] runs-on: ${{ matrix.runner }} + outputs: + digest-amd64: ${{ steps.digest.outputs.digest-amd64 }} + digest-arm64: ${{ steps.digest.outputs.digest-arm64 }} strategy: fail-fast: false matrix: @@ -41,7 +44,7 @@ jobs: - platform: arm64 runner: ubuntu-22.04-arm steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Free up disk space uses: jlumbroso/free-disk-space@v1.3.1 @@ -51,17 +54,18 @@ jobs: haskell: true large-packages: true - - uses: docker/setup-buildx-action@v1 + - uses: docker/setup-buildx-action@v3 - name: GHCR Log-in - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build Cache for Docker - uses: actions/cache@v3 + id: cache + uses: actions/cache@v4 with: path: var-ccache key: ${{ runner.os }}-${{ matrix.platform }}-build-cache-toolchain @@ -82,15 +86,18 @@ jobs: OWNER: '${{ github.repository_owner }}' - name: Build and push toolchain image + id: build uses: docker/build-push-action@v6 with: platforms: linux/${{ matrix.platform }} context: . file: Container/Dockerfile.toolchain push: true - tags: | - ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest-${{ matrix.platform }} - ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:${{ needs.prepare.outputs.docker_tag }}-${{ matrix.platform }} + outputs: type=image,name=ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain,annotation-index=true,name-canonical=true,push=true + + - name: Extract image digest + id: digest + run: echo "digest-${{ matrix.platform }}=${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT merge-toolchain-images: name: Merge Deeploy Toolchain Images @@ -98,7 +105,7 @@ jobs: needs: [ prepare, build-toolchain ] steps: - name: GHCR Log-in - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} @@ -110,8 +117,13 @@ jobs: env: OWNER: '${{ github.repository_owner }}' - - uses: Noelware/docker-manifest-action@v1 + - name: Merge Toolchain Images + uses: Noelware/docker-manifest-action@v1 with: - inputs: ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest-amd64,ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest-arm64 - tags: ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest,ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:${{ needs.prepare.outputs.docker_tag }} + inputs: | + ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain@${{ needs.build-toolchain.outputs.digest-amd64 }}, + ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain@${{ needs.build-toolchain.outputs.digest-arm64 }} + tags: | + ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest, + ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:${{ needs.prepare.outputs.docker_tag }} push: true \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5bd1a701..ab4aed6e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,16 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) +- Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) ### Added -- +- Output Docker image digests per platform (`amd64`, `arm64`) after build, which is used to construct the multi-arch Docker manifest. This preventes registry clutter caused by unnecessary per-architecture Docker tags. ### Changed -- +- Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. ### Fixed -- +- Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. ### Removed - From f3da691c9569473132878859ccc0cc14951a8415 Mon Sep 17 00:00:00 2001 From: Viviane <86701002+viv-eth@users.noreply.github.com> Date: Tue, 19 Aug 2025 08:40:35 -0700 Subject: [PATCH 03/28] [NetworkDeployer] Node Mangling to avoid duplication (#93) * [NetworkDeployer] Mangle these n...odes * [DeeployTypes] Only mangle on duplicates * Update changelog --------- Co-authored-by: viv-eth --- CHANGELOG.md | 3 +++ Deeploy/DeeployTypes.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab4aed6e73..9517069e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,16 +3,19 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) ### Added +- Added `_mangleNodeNames` function to avoid duplicate node mappings - Output Docker image digests per platform (`amd64`, `arm64`) after build, which is used to construct the multi-arch Docker manifest. This preventes registry clutter caused by unnecessary per-architecture Docker tags. ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. ### Fixed +- Prevent node duplication for graphs generated via GraphSurgeon - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. ### Removed diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index bd6145efe6..c7392a6786 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -3303,6 +3303,24 @@ def _mangleTensorNames(self): for tensor in self.graph.tensors().values(): tensor.name = f"{tensor.name}_tensor" + # Don't override this + def _mangleNodeNames(self): + """Mangle node names only if duplicates exist. Unique names are preserved.""" + # Count occurrences of each original name + counts: Dict[str, int] = {} + for node in self.graph.nodes: + counts[node.name] = counts.get(node.name, 0) + 1 + + # For any name that appears more than once, append a counter suffix + seen: Dict[str, int] = {} + for node in self.graph.nodes: + orig = node.name + if counts[orig] > 1: + idx = seen.get(orig, 0) + node.name = f"{orig}_{idx}" + seen[orig] = idx + 1 + # else: unique name, leave it unchanged + # Don't override this def _removeIdentityNodes(self): for node in filter(lambda x: x.op == "Identity", self.graph.nodes): @@ -3316,6 +3334,8 @@ def frontEnd(self): self._mangleTensorNames() + self._mangleNodeNames() + # Rename graph inputs and outputs: for idx, inputNode in enumerate(self.graph.inputs): inputNode.name = "input_" + str(idx) From f4cce776bc053cfd9dadeb8858e782f20ae5fc39 Mon Sep 17 00:00:00 2001 From: Viviane <86701002+viv-eth@users.noreply.github.com> Date: Wed, 27 Aug 2025 09:31:40 -0700 Subject: [PATCH 04/28] [DeeployTest] Change order of typeMatching entries (#68) * [DeeployTest] Change order of typeMatching entries * [Tests] Add negative values to correctly match type * [ci] Add tests for manual type inference * [DeeployTest] Add manual type inference feature * [CHANGELOG] Update with manual type inference feature * [DeeployTest] Align command line args with network generator * [CHANGELOG] Add PR to list of PRs * [DeeployTest] Remove non-ASCII chars * [DeeployTest] Move to Numpy-style docs * [DeeployTest] Fix input/output indexing error by zipping input names and arrays * Fix CI Tests - Add GitHub tests - Remove outdated GitLab CI file - Add support for `--shouldFail` for network generation * Fix Changelog * Improve debugging and implement CodeRabbit suggestions * Implement PR feedback for Luka * Fix CI --------- Co-authored-by: viv-eth Co-authored-by: Philip Wiese --- .github/workflows/CI.yml | 46 ++ .gitlab-ci.yml | 717 ------------------ .vscode/launch.json | 13 +- CHANGELOG.md | 5 +- DeeployTest/Tests/Adder/inputs.npz | Bin 2494 -> 1530 bytes DeeployTest/Tests/Adder/network.onnx | 15 +- DeeployTest/Tests/Adder/outputs.npz | Bin 1258 -> 756 bytes .../inputs.npz | Bin 0 -> 2224 bytes .../network.onnx | 31 + .../outputs.npz | Bin 0 -> 756 bytes DeeployTest/generateNetwork.py | 133 +++- DeeployTest/testMVP.py | 3 +- DeeployTest/testUtils/codeGenerate.py | 30 +- DeeployTest/testUtils/testRunner.py | 18 + DeeployTest/testUtils/typeMapping.py | 88 ++- 15 files changed, 315 insertions(+), 784 deletions(-) delete mode 100644 .gitlab-ci.yml create mode 100644 DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz create mode 100644 DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx create mode 100644 DeeployTest/Tests/testTypeInferenceDifferentTypes/outputs.npz diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4b74c66f97..4f2c5a4919 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1025,3 +1025,49 @@ jobs: run: | grep -Lr "SPDX-License-Identifier: Apache-2.0" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="runtime" | grep ".*\.h$" || [[ $? == 1 ]] shell: bash + + generate-network-type-inference: + runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} + needs: select-docker-image-and-runner + container: + image: ${{ needs.select-docker-image-and-runner.outputs.image }} + strategy: + fail-fast: false + matrix: + include: + - name: fail-input0 + platform: Generic + test: testTypeInferenceDifferentTypes + 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: testTypeInferenceDifferentTypes + 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: testTypeInferenceDifferentTypes + 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 + run: pip install -e . + - name: Run Test + 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/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 94318a4e9d..0000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,717 +0,0 @@ -variables: - GIT_SUBMODULE_STRATEGY: recursive - FF_USE_FASTZIP: "true" - # These can be specified per job or per pipeline - ARTIFACT_COMPRESSION_LEVEL: "fastest" - CACHE_COMPRESSION_LEVEL: "fastest" - TOOLCHAIN: "LLVM" - CMAKE_GENERATOR: "Ninja" - -stages: # List of stages for jobs, and their order of execution - - test - -.setup_test: - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - cd DeeployTest - - git lfs pull - -build_deeploy: # This job runs in the build stage, which runs first. - stage: test - resource_group: install - artifacts: - untracked: true - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - pip install -e . - - rm -f DeeployTest/out.txt - -gen_docs: - stage: test - resource_group: install - artifacts: - untracked: true - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - make docs - -run_cmsis_test_models: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - qemu-arm - parallel: - matrix: - - TEST: [simpleRegression, WaveFormer] - script: - - !reference [.setup_test, script] - - python testRunner_cortexm.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_QEMU/Tests/$TEST/*.c - - ./DeeployTest/TEST_QEMU/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_cmsis_test_kernels: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - qemu-arm - parallel: - matrix: - - TEST: [Adder, MultIO, test1DPad, test2DPad, testMatMul, testMatMulAdd, testMaxPool, testRQConv, testReduceSum, testReduceMean, testSlice] - script: - - !reference [.setup_test, script] - - python testRunner_cortexm.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_QEMU/Tests/$TEST/*.c - - ./DeeployTest/TEST_QEMU/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_test_models: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: [simpleRegression, miniMobileNet, miniMobileNetv2, Attention, MLPerf/KeywordSpotting, MLPerf/ImageClassification, MLPerf/AnomalyDetection] - script: - - !reference [.setup_test, script] - - python testRunner_siracusa.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_test_kernels: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: [Adder, MultIO, test1DPad, test2DPad, testMatMul, testMatMulAdd, testRequantizedDWConv, test2DRequantizedConv, iSoftmax, testConcat, testRMSNorm, trueIntegerDivSandwich, Hardswish, RQHardswish, testBacktracking] - script: - - !reference [.setup_test, script] - - python testRunner_siracusa.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_DMA_slice_L2: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - script: - - !reference [.setup_test, script] - - python testSlice_PULP.py --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/testSlice/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/testSlice/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_tiled_kernels_singlebuffer_L2: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: "testMatMul" - L1: [64000, 32000, 16000] - - TEST: "test2DRequantizedConv" - L1: [8000, 6000, 4000] - - TEST: "testRequantizedDWConv" - L1: [2561] # SCHEREMO: The implicit transpose after the conv is untiled; need at least 2560 - - TEST: "iSoftmax" - L1: [800, 500, 300] - - TEST: "testConcat" - L1: [32000, 16000, 8000] - - TEST: "testRMSNorm" - L1: [2048, 1024, 512] - - TEST: "Hardswish" - L1: [750] - - TEST: "RQHardswish" - L1: [750] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_tiled_kernels_doublebuffer_L2: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: "testMatMul" - L1: [64000, 32000, 16000] - - TEST: "test2DRequantizedConv" - L1: [8000, 6000, 5000] - - TEST: "testRequantizedDWConv" - L1: [5121] # SCHEREMO: The implicit transpose after the conv is untiled; need at least 2560 * 2 for DB - - TEST: "iSoftmax" - L1: [1600, 1000, 600] - - TEST: "testConcat" - L1: [64000, 32000, 16000] - - TEST: "testRMSNorm" - L1: [4096, 2048, 1024] - - TEST: "Hardswish" - L1: [750] - - TEST: "RQHardswish" - L1: [750] - - TEST: "microLlama/microLlama1" - L1: [60000, 20000, 10000] - - TEST: "microLlama/microLlama8" - L1: [60000, 20000, 10000] - - TEST: "microLlama/microLlama8_parallel" - L1: [60000, 20000, 10000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --doublebuffer - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_tiled_models_singlebuffer_L2: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: "simpleRegression" - L1: [45000, 30000, 15000] - - TEST: "miniMobileNet" - L1: [60000, 12000, 6000, 3000] - - TEST: "miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - TEST: "Attention" - L1: [60000, 10000, 5000] - - TEST: "microLlama/microLlama1" - L1: [60000, 10000, 5000] - - TEST: "microLlama/microLlama8" - L1: [60000, 10000, 5000] - - TEST: "microLlama/microLlama8_parallel" - L1: [60000, 10000, 5000] - - TEST: "MLPerf/KeywordSpotting" - L1: [64000] - - TEST: "MLPerf/ImageClassification" - L1: [64000] - - TEST: "MLPerf/AnomalyDetection" - L1: [64000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_tiled_models_singlebuffer_L3: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: "simpleRegression" - L1: [45000, 30000, 16000] # SCHEREMO: 15000 leads to non-2d transfers in L3! - - TEST: "miniMobileNet" - L1: [60000, 12000, 6000] # SCHEREMO: 3000 leads to non-2d transfers in L3! - - TEST: "miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - TEST: "Attention" - L1: [60000, 10000, 5000, 2500] - - TEST: "Transformer" - L1: [60000, 30000, 15000] - - TEST: "microLlama/microLlama1" - L1: [60000, 10000, 5000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --defaultMemLevel=L3 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - - -run_siracusa_tiled_models_doublebuffer_L3: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - PULP - parallel: - matrix: - - TEST: "simpleRegression" - L1: [60000, 45000, 30000] - - TEST: "miniMobileNet" - L1: [60000, 24000, 12000, 6000] - - TEST: "miniMobileNetv2" - L1: [60000, 32000, 24000, 16000] - - TEST: "Attention" - L1: [60000, 20000, 10000, 5000] - - TEST: "Transformer" - L1: [60000, 30000, 15000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --doublebuffer --defaultMemLevel=L3 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - - -run_siracusa_w_neureka_tiled_kernels_singlebuffer_L2: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "testRequantizedLinear" - L1: [16000] - - TEST: "testPointwise" - L1: [32000] - - TEST: "testPointwiseConvBNReLU" - L1: [32000] - - TEST: "testPointwiseUnsignedWeights" - L1: [32000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --defaultMemLevel=L2 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - - -run_siracusa_w_neureka_tiled_kernels_doublebuffer_L2: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "testRequantizedLinear" - L1: [16000] - - TEST: "testPointwise" - L1: [32000] - - TEST: "testPointwiseConvBNReLU" - L1: [32000] - - TEST: "testPointwiseUnsignedWeights" - L1: [32000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --defaultMemLevel=L2 --doublebuffer - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_w_neureka_tiled_models_singlebuffer_L3: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - TEST: "Attention" - L1: [2500] - - TEST: "Transformer" - L1: [15000] - - TEST: "microLlama/microLlama1" - L1: [10000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --defaultMemLevel=L3 - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_w_neureka_tiled_models_doublebuffer_L3: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - TEST: "Attention" - L1: [5000] - - TEST: "Transformer" - L1: [30000] - script: - - !reference [.setup_test, script] - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --defaultMemLevel=L3 --doublebuffer - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_w_neureka_tiled_kernels_singlebuffer_L2_wmem: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "testRequantizedLinear" - L1: [16000] - - TEST: "testPointwise" - L1: [32000] - - TEST: "testPointwiseConvBNReLU" - L1: [32000] - - TEST: "testPointwiseUnsignedWeights" - L1: [32000] - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - cd DeeployTest - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --defaultMemLevel=L2 --neureka-wmem - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_siracusa_w_neureka_tiled_models_doublebuffer_L3_wmem: - stage: test - tags: - - PULP - parallel: - matrix: - - TEST: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - TEST: "Attention" - L1: [2500] - - TEST: "Transformer" - L1: [30000] - - TEST: "microLlama/microLlama1" - L1: [10000] - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - cd DeeployTest - - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/$TEST --l1 $L1 --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR --cores=8 --defaultMemLevel=L3 --doublebuffer --neureka-wmem - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.c - - ./DeeployTest/TEST_SIRACUSA_W_NEUREKA/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_mempool_test_kernels: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - banshee - retry: 2 - parallel: - matrix: - - TEST: [Adder, MultIO, test1DConvolution, test2DConvolution, test1DDWConvolution, test2DDWConvolution, test1DPad, test2DPad, testGEMM, testMatMul, testMatMulAdd, testMaxPool, testRQConv, testRQGEMM, testRQMatMul, testReduceSum, testReduceMean, testSlice, testRequantizedDWConv, test2DRequantizedConv] - script: - - !reference [.setup_test, script] - - python testRunner_mempool.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_MEMPOOL/Tests/$TEST/*.c - - ./DeeployTest/TEST_MEMPOOL/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_mempool_test_models: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - tags: - - banshee - retry: 2 - parallel: - matrix: - - TEST: [simpleRegression, simpleCNN, ICCT, ICCT_ITA, ICCT_8, ICCT_ITA_8, miniMobileNet, miniMobileNetv2] - script: - - !reference [.setup_test, script] - - python testRunner_mempool.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - # - python testRunner_mempool.py -t ./Tests/WaveFormer -DGCC_INSTALL_DIR=$MEMPOOL_GCC_INSTALL_DIR # Boken with ITA (heap is too small) - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_MEMPOOL/Tests/$TEST/*.c - - ./DeeployTest/TEST_MEMPOOL/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_generic_test_kernels: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - parallel: - matrix: - - TEST: [Adder, MultIO, test1DConvolution, test2DConvolution, test1DDWConvolution, test2DDWConvolution, test1DPad, test2DPad, testConcat, testGEMM, testMatMul, testMatMulAdd, testMaxPool, testRQConv, testRQMatMul, testReduceSum, testReduceMean, testSlice, testRequantizedDWConv, test2DRequantizedConv, iSoftmax] - script: - - !reference [.setup_test, script] - - python testRunner_generic.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_GENERIC/Tests/$TEST/*.c - - ./DeeployTest/TEST_GENERIC/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -run_generic_test_models: # This job runs in the test stage. - stage: test # It only starts when the job in the build stage completes successfully. - parallel: - matrix: - - TEST: [simpleRegression, WaveFormer, simpleCNN, ICCT, ICCT_ITA, ICCT_8, ICCT_ITA_8, miniMobileNet, miniMobileNetv2] - script: - - !reference [.setup_test, script] - - python testRunner_generic.py -t ./Tests/$TEST --toolchain=$TOOLCHAIN --toolchain_install_dir=$LLVM_INSTALL_DIR - artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA" - paths: - - ./DeeployTest/out.txt - - ./DeeployTest/TEST_GENERIC/Tests/$TEST/*.c - - ./DeeployTest/TEST_GENERIC/Tests/$TEST/*.h - expire_in: 4 weeks - cache: - key: $CI_PROJECT_DIR-$CI_COMMIT_REF_SLUG - paths: - - ./DeeployTest/TEST_*/build - -test_deeploy_state_serialization: - stage: test - parallel: - matrix: - - TEST: [simpleRegression] - PLATFORM: ['QEMU-ARM', 'Siracusa', 'MemPool', 'Generic'] - script: - - !reference [.setup_test, script] - - python deeployStateEqualityTest.py -t ./Tests/$TEST -p $PLATFORM - -test_memory_level_extension: - stage: test - parallel: - matrix: - - TEST: [simpleRegression] - PLATFORM: ['QEMU-ARM', 'Siracusa', 'MemPool', 'Generic'] - script: - - !reference [.setup_test, script] - - python testMemoryLevelExtension.py -t ./Tests/$TEST -p $PLATFORM - -test_tiler_extension: - stage: test - parallel: - matrix: - - TEST: [simpleRegression, simpleCNN, testMatMul, testMaxPool] - PLATFORM: ['Siracusa'] - script: - - !reference [.setup_test, script] - - python testTilerExtension.py -t ./Tests/$TEST -p $PLATFORM - -test_tiler_extension_fails: - stage: test - parallel: - matrix: - - TEST: [simpleRegression, simpleCNN, testMatMul] - PLATFORM: ['Siracusa'] - script: - - !reference [.setup_test, script] - - python testTilerExtension.py -t ./Tests/$TEST -p $PLATFORM --l1 2000 --shouldFail - -test_memory_allocation_extension: - stage: test - parallel: - matrix: - - TEST: [simpleRegression, simpleCNN, miniMobileNet, miniMobileNetv2, testMatMul, testMaxPool] - PLATFORM: ['Siracusa'] - script: - - !reference [.setup_test, script] - - python testTilerExtension.py -t ./Tests/$TEST -p $PLATFORM - -test_deeploy_typing: - stage: test - script: - - !reference [.setup_test, script] - - python testTypes.py - -test_regex_matching: - stage: test - script: - - !reference [.setup_test, script] - - python testRegexMatching.py - -format_python: - stage: test - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . - -format_python_imports: - stage: test - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - isort --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c -v - - autoflake -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "*/third_party/**" ./ - -format_c: - stage: test - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -ir --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format ./ scripts - -lint_python_licenses: - stage: test - variables: - LICENSE_STRING: "SPDX-License-Identifier: Apache-2.0" - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - grep -Lr "$LICENSE_STRING" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude "run_clang_format.py" | grep ".*\.py$" || [[ $? == 1 ]] - -lint_c_licenses: - stage: test - variables: - LICENSE_STRING: "SPDX-License-Identifier: Apache-2.0" - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - grep -Lr "$LICENSE_STRING" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="runtime" | grep ".*\.c$" || [[ $? == 1 ]] - -lint_c_header_licenses: - stage: test - variables: - LICENSE_STRING: "SPDX-License-Identifier: Apache-2.0" - script: - - bash && source ~/.bashrc - - $CONDA activate dumpoci - - export PYTHONPATH=`pwd`:$PYTHONPATH - - grep -Lr "$LICENSE_STRING" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="runtime" | grep ".*\.h$" || [[ $? == 1 ]] diff --git a/.vscode/launch.json b/.vscode/launch.json index 6703ff81b6..09ee03fed4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -58,8 +58,17 @@ "command": "extension.commandvariable.file.pickFile", "args": { "description": "Select ONNX File", - "include": "DeeployTest/Tests/**/*.onnx", - "transform": { + "include": "**/*.onnx", + "display": "transform", + "fromFolder": { + "fixed": "${workspaceFolder}/DeeployTest/Tests" + }, + "labelTransform": { + "text": "${fileDirname}", + "find": ".*[\\/]", + "replace": "" + }, + "valueTransform": { "text": "${fileDirname}" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9517069e4c..9e056c0213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,14 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Change order of typeMatching entries [#68](https://github.com/pulp-platform/Deeploy/pull/68) - Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) ### Added +- Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough +- Added a `testTypeInferenceDifferentTypes` test case to validate type inference for different input types - Added `_mangleNodeNames` function to avoid duplicate node mappings - Output Docker image digests per platform (`amd64`, `arm64`) after build, which is used to construct the multi-arch Docker manifest. This preventes registry clutter caused by unnecessary per-architecture Docker tags. @@ -19,7 +22,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. ### Removed -- +- Delete outdated and unused `.gitlab-ci.yml` file ## Release v0.2.0 (2025-07-08) [#103](https://github.com/pulp-platform/Deeploy/pull/103) This release containing major architectural changes, new platform support, enhanced simulation workflows, floating-point kernel support, training infrastructure for CCT models, memory allocation strategies, and documentation improvements. diff --git a/DeeployTest/Tests/Adder/inputs.npz b/DeeployTest/Tests/Adder/inputs.npz index e74c7e5ad2d9830973afd3947b3311c705e5d2d6..6b104c7770b2072f5db0e42578463283b5072ac3 100644 GIT binary patch literal 1530 zcmd6nPe_w-7{{MYjfkKfcJR>Q4TKp;OsI=^m@*=8$qohvfl8Z1$Q)C`YQc~Q5s_gY zI)q4sNO%Y_84)tyI&=_`5D^I(;z1%}hY*pFKHt3sDRk-7s~^7K=lT78pFLZ=t*Sa` z-gCj0R|cyG{bu5v1+71o8ft24NhG?$ms08bJ_}TaG+k5lJZ-;mJ$}bq`LYuiKOyZd-?{Frbu!lpe zJ1;QyT;L<{6~B(^9tGxZ;1|i2@p`hvb;R2LBYq!>_!1f>{~BFm|I_#xylT>kR_=^$ zGPZ!~yxapI512+21WP;Bd%FDd+DwgF`LB~@lRU4^H%Yr_#F8?_I`y| zJ+8r_%NlZeZ)5EQ@ptk&p!c33jziRqA8Xq7iNdtHQ5K@1`k zChJlVaPY(A49%gURP;W;7~^>uBd3C$MfHJHqbl$wYxH5384I8)^0ezUql!O;A3;~h zZ$KWeCL6~eq52Z(F6-!HP?O2OZS@-A2-V(dxLN!G-rk!vP>)cwHge*i{uSOks)l272D2L|Rw}jTi z5OlZ1+kF0D)!%+=sot+A=aV_{%X@P1@t*&^l#==0`2Sp7`3A(>YEEg2pT7s_-5Nzd E0VDNeApigX literal 2494 zcmd6pOHUI~6vs~iNp!`cOBbUtDVnAM6-BIi#fXmzRs|J&G>w#WVSu#6#Hh*n4ldpJ zQRWNyRb0DtruX;1aY)>_a)2Dpx%a&O=P}dmOwZIUK4)y~-+m2e%*wx6t6OiOwSV}r zW^)rsd8<4rpRXHR>)q{|eXviB-NE?XsIihY+I!25X4cp{7#)rJ`@MtF?x2*f_1}*N zg?v2h9}WtBezBP?#ozPI>`V3!fep&KUD9zy3M^_@t=3*=XkuOoj3AF6U&hJPDr z{yb896KV4Il6%Na_mPL!=q+;Z6?_K0f?RQshvK#;+`ANME_)A zwtCO;m*dCpRnG%?%WuG6*o^m_d|YwW(I;P9k(^U6W?%jrhf9Syzm+Yy2jvuplFUbG($opNW;=KtEPRd($Q=cgA8{EGi zsXcSWY22zT`h_j7Qw72=WIi^PMz>0!QXgLCG}T9Nk- za`iylU@AgvadeZekI;C57gC}YbPEjpH$b&)SZ6G)i=mf z->Gl4C*;?77O*4x!jXK^p4S}m9!U8yzpgwrfAoDW9R9Ljg{Lv6j=r-ObIq&rYZEW$ zdasyplRkJ0S5aesyZU4)+DrQC8`U$zpZseN(+|e}kbc^Gvd_E*^j&$`-6EgONOQe^)aSxYae{;1Yo@)Wxl=z2pH|hr=1lmc zc>(u?i|i0bvH!cB+EjhIZt*$(1% LGc0I0S#rMtht3rN diff --git a/DeeployTest/Tests/Adder/network.onnx b/DeeployTest/Tests/Adder/network.onnx index 851801aaa5..6c836a0ff3 100644 --- a/DeeployTest/Tests/Adder/network.onnx +++ b/DeeployTest/Tests/Adder/network.onnx @@ -1,7 +1,8 @@ -pytorch1.11.0:Å -) +pytorch2.7.1:¡ +( onnx::Add_0 - onnx::Add_12Add_0"Addtorch-jit-exportZ% + onnx::Add_12/Add"Add +main_graphZ% onnx::Add_0   @@ -19,10 +20,4 @@    -j -2 - - - - -B \ No newline at end of file +B \ No newline at end of file diff --git a/DeeployTest/Tests/Adder/outputs.npz b/DeeployTest/Tests/Adder/outputs.npz index 9a8d6680e38c6a38e1c31fdd30d71f11e2f9d0b5..f73b28d5511ef96e65451e8eb84f27a25390b8be 100644 GIT binary patch literal 756 zcmbV~y)Q#y6voeOweiuRkq#mfSCCuMP+tS_EhIGL4h%v2Lsn$XibNB$ajVU=+UJ_BfN9Mw$CL5!($sQ15>E-lBnUs@MSzhN>CON=?P~^w=v0r$ z23p`9km_Oi?E8oE%B_D;j_jj|g)Jb%5uKkXWeQr{9S6Xe+aZj%PT>KrkMDk}<+S1!tpPc_J zWbL|=SLK;JE?*w(R7ZvUkYDAno}Em~C$8KYJuW-09Gy+SPy3VJ*>qUv`gZ?xRxj$a zasRwt@CT1NF25gk+;4ZYap&5E?|H>{it)MPe5lxr6w@B{KKz4XdvwD5eud zf66?1?koHo>pm%l0B0Wu_hahEijDaIBj<4V@c5OA_3RT_KSwvBXZtMcUZ0D0&K>1` z7c`&n_=@^_MKS#Wb$q$c$|Lu*yqCLLPe&kmEPZj0@rBL@@{za7J$i}r2JR~!=)C3V z$RWOApMj#Fo6rlE8@hro&%EXC$xXIYC%#q;oHHGwe_t_K?%T@e1H}NE?wsd^e3IpB zeFV4jC7$>A4(t=iTeyd0die5iZ~Z}j5r3W>Jv#1-`i)(DTOW|G^^e`R)@#jWi<>My}g=Qv3PAR IuxVxX4-;*xfdBvi diff --git a/DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz b/DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..db396786bd431cdc9b6cc44c4ab44add452b915e GIT binary patch literal 2224 zcmd6pYfMx}6vzJ{C{|4X0ZmNmQmvq&h_Bix#s#_K19rMq6x3EBf~Yl$KoJzpYAvBc z6qO)WYeg$v3snSs8(bE5ik3U#i)<<4MyVy%HavXbi}YM+jGFXIKRLU<{Lh@3Gjq<} zxsx@9_i*t-ck{*OAeNNk3~0E*3n76k64RaF{=%V6(gw7)gU>b?=Q<%3YyINllNTlV zP0;xTFCOa`pz~Y2GASh~cE!S#NpbO-pT#aujwgTelGwy}>idrh(2eW<4iC_+)BTV3 z4$?N-&>A6dem%o7lYrN|3>9?@ro&-aa7!T9E^zO-K+_X}Ypo29I0gGY5!h^H*q1L5 zJ)hyDAp-6L6zKdI3fjp>YxqMz*K!`lfdURYL(E_s5=SX8@3q0PgQ0R0gYion`hG27 z{7JwPV8gVXHuOBgkl18{rH=xAmV!-31v+mi2$~~cuCbwUxIk?x!_XT7^G-0tg)oF| z5ojI35L9P_*}@Rr#4z(B!}1}t#~1~If~HDZyYM_rb{n=lpywOGpx>szGL!OdSFq+P!xGx3k)B^& zq=0Ey7&hq`MoSq!~gf>@_CWZi3QU_@SX&6yM3?+gHkY7*non)KN0db+geZoi- zkncxQGtG%4yPb%jei7lY0RE)fn%|SAkaiKxL>~3?iL9z_pN`^Nsoz2v$+pmbFXmI< zLBtT+9?hhBE3k>UMRqP}FkvLSfpj0OcbarR(M~>X4XqXzvMrR4?%(k})8e%}8_6dL2l>vDwphDk^^~g?r`0u-e6565QxM@E^7>J&-+S;vigWknsoknm z-qxcUdi$B|d|W3#8#7WiJ~hjl=f!g1G`l*wt<5mIccx(yKPBV6bJQn0i{#>SIR;zQ zhpJa<8OKIX!+~GFla_mJhCzc0)W~zU_|N6Fywh_Rm&K>Kn{x->wt9dZxa|)AAb%Zi zU*RL4%_`v|dUr_M$5+%fl?u-;?35|XXBZw=jp5$)5BSrC_tm(}&f1H*O4(MnB0TwS zA-{WQtRd{?efjzA-E!RG-}!;61{wRnEn?}IOxb14`^97*B6pMyk_Wdwl2a-!8gj2C z@w}x%9r^I0ynHZ$M~}=i_}u6h(JSx_Z%Nr8hpnH_^BbGhvjZzsc+|?sKOgh*K3~Xc z&s07+cZeE$Jc}PSyVZ`JUM|xv4CU!*OZe1@+xZ4na$EIPnV@SsCxO@;NtWhw-SVKk$lq4H4Jt^VP}q$HL1! z9?6>Elj^R&N(?C_4!-(wouPO^sbS|NAATu&hOBq_P3;#uK~3uNRXxsB^HKdBvdBA1 zE=r#%=VgqSe-t(Ir7mr9uJ2*#F|JOEg++2^@LqZKV3#4`gkG*XbxeMh?Jm=^&AjI7 zEZ%=ZvfL69r20OJRVQs9Esfz$&R#wK>n{LaHj|TPzW77%X2|PT@yiI9oQmnxzqpv+ f40-*Pcr|2>E4p70W4LQiZJ-Bzc9A-{X}x~{CGFSp literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx b/DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx new file mode 100644 index 0000000000..588abf9344 --- /dev/null +++ b/DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx @@ -0,0 +1,31 @@ + add_chain_test:± + +A +BXAdd1"Add + +X +CYAdd2"Addadd_chain_graphZ +A + + + + +Z +B + + + + +Z +C + + + + +b +Y + + + + +B \ No newline at end of file diff --git a/DeeployTest/Tests/testTypeInferenceDifferentTypes/outputs.npz b/DeeployTest/Tests/testTypeInferenceDifferentTypes/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..2269dd7292bd3e81b41c99ff754f67575a4e5388 GIT binary patch literal 756 zcmWIWW@Zs#fB;2?4_7>_N|+cJK$w+5gdtKdub`5VK>#cOQUsC!fysWMz5$Vp3}p<} z>M5zk$wlf`3hFkQCh9s0>S_5!B}IvO@%cq5sUUH;#GK+(pm=dcVnHg9uVJX8UD2E}qO|SgxOW~9s4b0H{O)_ryW-Z( zYrdq+5Zpa+))&{SR*_p8H8@W`658bd85*rnL2%p_`+h(K5nQC z7E!wOCDo&N^Y>JHKFgF_Vw_rGDdE*^rvkS<6@Hj+cuI49Gk^0kp0(;9bn5@VsubPjS1)eCstK*zMff(oVc1+Woq7JGMqw2u%eznaEVz2@ z-z|Qw>l#ypZ*GaOXgQY`CYji>)n=28@$($t)>*UWzO-EWtyRcF&YUU5c6zL{i|hXX z4fo9^O-y;rKBea6=Got8W|x1hnR8{&p^kqowhU6ozZ&^OyL{bn_wUss(aXw0jWoH> z%37J2$$EZ&l9nE~O?H~UQ7or=+gr6eHv})r@cnD?JGAc6sXe~ee;QrVyK3Rothm5r zwdJl0%+)T+kpkbg*X3|18$RLs7unQWD;S str: +def generateTestInputsHeader(deployer: NetworkDeployer, + test_inputs: List, + inputTypes: Dict, + inputOffsets: Dict, + verbose: Optional[bool] = None) -> str: retStr = "" inputNames = [deployer.ctxt.lookup(buf.name) for buf in deployer.graph.inputs] inputTypes = {buf.name: buf._type for buf in inputNames} @@ -97,6 +100,12 @@ def generateTestInputsHeader(deployer: NetworkDeployer, test_inputs: List, input ]) retStr += "};\n" + if verbose: + print('Input:') + for name in inputTypes.keys(): + buf = deployer.ctxt.lookup(name) + print(f" - '{name}': Type: {buf._type.referencedType.typeName}, Offset: {inputOffsets[name]}") + return retStr @@ -123,9 +132,9 @@ def generateTestOutputsHeader(deployer: NetworkDeployer, data_type = output_data_type[f"output_{index}"] isdatafloat = (data_type.referencedType.typeName == "float32_t") + output_n_levels[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}').nLevels + output_signed[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}')._signed if signProp and not isdatafloat: - output_n_levels[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}').nLevels - output_signed[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}')._signed test_outputs[index] -= int( ((1 - output_signed[f"output_{index}"]) * (output_n_levels[f"output_{index}"] / 2))) @@ -159,13 +168,14 @@ def generateTestOutputsHeader(deployer: NetworkDeployer, retStr += "};\n" if verbose: + print('Output:') if signProp: - print('Output N Levels:') - pprint(output_n_levels, indent = 2, width = 120) - print('Output Signed:') - pprint(output_signed, indent = 2, width = 120) - print('Output Data Type:') - pprint(output_data_type, indent = 2, width = 120) + for (name, buf), (_, n_level), (_, signed) in zip(output_data_type.items(), output_n_levels.items(), + output_signed.items()): + print(f" - '{name}': Type: {buf.referencedType.typeName}, nLevels: {n_level}, Signed: {signed}") + else: + for (name, buf) in output_data_type.items(): + print(f" - '{name}': Type: {buf.referencedType.typeName}") return retStr diff --git a/DeeployTest/testUtils/testRunner.py b/DeeployTest/testUtils/testRunner.py index ce51fda15e..a3dc6a7189 100644 --- a/DeeployTest/testUtils/testRunner.py +++ b/DeeployTest/testUtils/testRunner.py @@ -177,6 +177,20 @@ def __init__(self, tiling_arguments: bool, description = None): type = str, default = os.environ.get('LLVM_INSTALL_DIR'), help = 'Pick compiler install dir\n') + self.add_argument('--input-type-map', + nargs = '*', + default = [], + type = str, + help = '(Optional) mapping of input names to data types. ' + 'If not specified, types are inferred from the input data. ' + 'Example: --input-type-map input_0=int8_t input_1=float32_t ...') + self.add_argument('--input-offset-map', + nargs = '*', + default = [], + type = str, + help = '(Optional) mapping of input names to offsets. ' + 'If not specified, offsets are set to 0. ' + 'Example: --input-offset-map input_0=0 input_1=128 ...') if self.tiling_arguments: self.add_argument('--defaultMemLevel', @@ -244,6 +258,10 @@ def generate_cmd_args(self) -> str: command += " --debug" if hasattr(self.args, 'profileUntiled') and self.args.profileUntiled: command += " --profileUntiled" + if self.args.input_type_map: + command += " --input-type-map " + " ".join(self.args.input_type_map) + if self.args.input_offset_map: + command += " --input-offset-map " + " ".join(self.args.input_offset_map) if self.tiling_arguments: if self.args.defaultMemLevel: diff --git a/DeeployTest/testUtils/typeMapping.py b/DeeployTest/testUtils/typeMapping.py index 4cb18cb8f4..a551b25150 100644 --- a/DeeployTest/testUtils/typeMapping.py +++ b/DeeployTest/testUtils/typeMapping.py @@ -24,7 +24,7 @@ # limitations under the License. from collections import namedtuple -from typing import List, Optional +from typing import List import numpy as np @@ -33,6 +33,32 @@ offsetType = namedtuple("offsetType", ("type", "offset")) +_ALL_DTYPES: dict[str, type] = {t.typeName: t for t in (*IntegerDataTypes, *FloatDataTypes)} + + +def parseDataType(name: str) -> type: + """Parses a data type from its name. + + Parameters + ---------- + name : str + The name of the data type. + + Returns + ------- + class + The corresponding data type class. + + Raises + ------ + ValueError + If the provided data type name is unknown. + """ + if name not in _ALL_DTYPES: + allowed = ", ".join(sorted(_ALL_DTYPES)) + raise ValueError(f"Unknown data type: {name}. Allowed: {allowed}") + return _ALL_DTYPES[name] + def isInteger(_input: np.array) -> bool: if np.abs((_input.astype(int) - _input)).max() > 0.001: @@ -58,41 +84,63 @@ def dataWidth(n): return ret -def inferInputType(_input: np.ndarray, - signProp: Optional[bool] = None, - defaultType = PointerClass(int8_t), +def inferInputType(values: np.ndarray, + signProp: bool = False, + defaultType = int8_t, defaultOffset = 0) -> List[offsetType]: + """Infers the data type of the provided input array. + + Parameters + ---------- + values : np.ndarray + The input array for which to infer the data type. + + signProp : bool + Whether to consider signedness when inferring the data type. + + defaultType : type + The default data type to use if inference fails. + + defaultOffset : int + The default offset to use if inference fails. + + Returns + ------- + List[offsetType] + A list of inferred data types and their corresponding offsets. + """ # WIESEP: We cannot do type inference for empty arrays. - if np.prod(_input.shape) == 0: - print(f"Warning: Empty input array for type inference for {_input}!") + if np.prod(values.shape) == 0: + print(f"Warning: Empty input array for type inference for {values}!") return [(defaultType, defaultOffset)] - if signProp is None: - signProp = False - signedPlatformTypes = [_type for _type in IntegerDataTypes if _type.typeMin < 0] matchingTypes = [] - # FIXME: this is okay for now (3 distinctions are fine), but there is implicit - # knowledge encoded in the order of the checks (i.e. first unsigned, signed - # and then float). It might be good to extract that implicit knowledge into an ordered list. - if signProp and isUnsigned(_input) and isInteger(_input): + # There is implicit knowledge encoded in the order of the checks (i.e. first unsigned, signed + # and then float). + if signProp and isUnsigned(values) and isInteger(values): for _type in sorted(signedPlatformTypes, key = lambda x: x.typeWidth): signPropOffset = (2**(_type.typeWidth - 1)) - if _type.checkPromotion(_input - signPropOffset): + if _type.checkPromotion(values - signPropOffset): matchingTypes.append(offsetType(PointerClass(_type), signPropOffset)) - elif isInteger(_input): - for _type in sorted(IntegerDataTypes, key = lambda x: x.typeWidth): - if _type.checkPromotion(_input): + elif isInteger(values): + sorted_types = sorted( + IntegerDataTypes, + key = lambda t: (t.typeWidth, t.typeMin < 0), + ) + + for _type in sorted_types: + if _type.checkPromotion(values): matchingTypes.append(offsetType(PointerClass(_type), 0)) else: for _type in sorted(FloatDataTypes, key = lambda x: x.typeWidth): - if _type.checkPromotion(_input): + if _type.checkPromotion(values): matchingTypes.append(offsetType(PointerClass(_type), 0)) - if matchingTypes == []: - raise Exception("Could not find a matching type!") + if not matchingTypes: + raise RuntimeError("Could not find a matching type!") return matchingTypes From 05d640374d6e56e0d68503ddd00d51a6ab9c7c0b Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Wed, 10 Sep 2025 09:46:59 +0200 Subject: [PATCH 05/28] Refactor tiling code generation (#105) * Refactor mchan hal * Refactor IntrospectiveCodeTransformation * Refactor MemoryAllocation * Add minimalIntegerType helper function * Small refactor DeeployTypes * Change Neureka tile constraints to new TilingCodegen function * Small refactors Check for LLVM_INSTALL_DIR environment variable Fix typo Check for SNITCH_HOME environment variable and crash if not present Change test output difference to absolute difference Improve engine coloring error message Fix type hint * Permutation refactor * Refactor TransposeTileConstraint * Remove manual name mangling from templates since it's automatically done in the ExecutionBlock.generate() * Change serialize to produce same shape rank as original * Refactor TilingExtension * Port PULPOpen * Port Snitch * DeeployTest: Extract generic tiling code into tilingUtils.py * DeeployTest: Extract common test generation code * DeeployTest: Add Dma tests * Apply Philip's comments Remove dory_dma.h Fix hoistReference doc comment Use the shape argument of the _hoistReference function Rename dma test runners Change kernelLevelTiling HACK comment to a TODO Add DMA folder to targets with DMAs Fix wrong deeployStateDir Single source of truth for the tiling arena name * Add unravelReference doc comment and fix the dealiasBuffer's * Refactor type inference and minimal(Integer|Float)Type * Revert extra inputs hack * Add mchan check for both event- and poll-based event checking flags being set * Fix HyperRectangle arg order * Fix mchan check whether size is representable within 17 bits * Fix init, deinit, wait on initialFuture in DoubleBuffering, rename gen to anydimAdapter * Fix GEMM tile constraint serialization to check transA and transB * Fix inherit from ABC in AsyncDma and AsyncDmaWaitingStrategy * Fix use tileSizeInBytes to check whether it fits in memory * Update changelog * Add missing transferOpRepr abstract method from the BlockingAsyncDmaAdapter --- .github/workflows/CI.yml | 18 + CHANGELOG.md | 33 + .../CodeTransformationPasses/Closure.py | 4 +- .../IntrospectiveCodeTransformation.py | 199 +++--- .../MemoryAllocation.py | 169 ++--- Deeploy/CommonExtensions/DataTypes.py | 34 +- .../LoweringOptimizationPasses.py | 83 +-- Deeploy/DeeployTypes.py | 230 +++--- .../EngineColoringDeployer.py | 7 +- .../Targets/CortexM/Templates/CMSISUtils.py | 4 +- .../Generic/Templates/DebugPrintTemplate.py | 2 +- .../Generic/Templates/ITAMaxTemplate.py | 2 +- .../TransposeTileConstraint.py | 37 +- .../TileConstraints/iRMSNormTileConstraint.py | 9 +- .../Targets/MemPool/Templates/GemmTemplate.py | 18 +- .../MemPool/Templates/ITAMaxTemplate.py | 2 +- .../Targets/MemPool/Templates/ITATemplate.py | 5 +- .../MemPool/Templates/RQGemmTemplate.py | 18 +- .../MemPool/Templates/RQMatMulTemplate.py | 12 +- .../TileConstraints/NeurekaDenseConstraint.py | 4 +- .../NeurekaDepthwiseConstraint.py | 4 +- .../NeurekaPointwiseConstraint.py | 4 +- Deeploy/Targets/PULPOpen/Bindings.py | 21 +- .../AutoTransposeUtils.py | 27 +- .../PULPClusterTiling.py | 34 +- .../PULPClusterTilingDB.py | 359 ---------- .../PULPClusterTilingSB.py | 673 ------------------ .../CodeTransformationPasses/PULPL3Tiling.py | 34 +- .../PULPL3TilingDB.py | 329 --------- .../PULPL3TilingSB.py | 468 ------------ Deeploy/Targets/PULPOpen/DMA/L3Dma.py | 53 ++ Deeploy/Targets/PULPOpen/DMA/MchanDma.py | 66 ++ Deeploy/Targets/PULPOpen/Platform.py | 4 +- .../TileConstraints/GEMMTileConstraint.py | 118 ++- .../TileConstraints/MatMulTileConstraint.py | 44 +- .../SoftmaxCrossEntropyTileConstraint.py | 2 +- Deeploy/Targets/Snitch/Bindings.py | 7 +- .../SnitchClusterTiling.py | 27 +- .../SnitchClusterTilingSB.py | 520 -------------- Deeploy/Targets/Snitch/DMA/SnitchDma.py | 51 ++ Deeploy/TilingExtension/AsyncDma.py | 247 +++++++ .../DoubleBufferingTilingCodeGeneration.py | 249 +++++++ .../SingleBufferingTilingCodeGeneration.py | 153 ++++ .../TilingCodeGeneration.py | 281 +++++--- .../TilingHoistingMixIn.py | 149 ++++ .../TilingPrototypes.py | 156 ++-- .../TilingVariableReplacement.py | 325 ++++----- Deeploy/TilingExtension/MemoryConstraints.py | 2 +- Deeploy/TilingExtension/MemoryScheduler.py | 7 +- Deeploy/TilingExtension/TileConstraint.py | 52 +- Deeploy/TilingExtension/TilerExtension.py | 70 +- Deeploy/TilingExtension/TilingCodegen.py | 235 +++--- .../Platforms/Siracusa/src/deeploytest.c | 3 +- DeeployTest/deeployStateEqualityTest.py | 4 +- DeeployTest/generateNetwork.py | 74 +- DeeployTest/testDebugPrintPass.py | 7 +- DeeployTest/testDmas.py | 68 ++ DeeployTest/testMVP.py | 146 +--- DeeployTest/testMemoryLevelExtension.py | 4 +- .../testPrintInputOutputTransformation.py | 7 +- DeeployTest/testRunner_siracusa_l3dma.py | 94 +++ DeeployTest/testRunner_siracusa_mchandma.py | 95 +++ DeeployTest/testRunner_snitch_dma.py | 100 +++ DeeployTest/testSchedulingExtension.py | 4 +- DeeployTest/testSlice_PULP.py | 54 +- DeeployTest/testTilerExtension.py | 4 +- DeeployTest/testUtils/codeGenerate.py | 189 +++-- DeeployTest/testUtils/dmaUtils.py | 373 ++++++++++ DeeployTest/testUtils/platformMapping.py | 5 +- DeeployTest/testUtils/testRunner.py | 1 + DeeployTest/testUtils/tilingUtils.py | 41 ++ DeeployTest/testUtils/typeMapping.py | 146 ++-- TargetLibraries/PULPOpen/CMakeLists.txt | 2 +- TargetLibraries/PULPOpen/inc/dory_dma.h | 53 -- TargetLibraries/PULPOpen/inc/mchan.h | 161 ----- TargetLibraries/PULPOpen/inc/mchan_siracusa.h | 15 + TargetLibraries/PULPOpen/inc/mchan_v6.h | 112 +++ TargetLibraries/PULPOpen/inc/mchan_v7.h | 138 ++++ TargetLibraries/PULPOpen/src/dory_dma.c | 228 ------ cmake/snitch/snitch.cmake | 4 + 80 files changed, 3579 insertions(+), 4214 deletions(-) delete mode 100644 Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingDB.py delete mode 100644 Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingSB.py delete mode 100644 Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingDB.py delete mode 100644 Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingSB.py create mode 100644 Deeploy/Targets/PULPOpen/DMA/L3Dma.py create mode 100644 Deeploy/Targets/PULPOpen/DMA/MchanDma.py delete mode 100644 Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTilingSB.py create mode 100644 Deeploy/Targets/Snitch/DMA/SnitchDma.py create mode 100644 Deeploy/TilingExtension/AsyncDma.py create mode 100644 Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py create mode 100644 Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py create mode 100644 Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py create mode 100644 DeeployTest/testDmas.py create mode 100644 DeeployTest/testRunner_siracusa_l3dma.py create mode 100644 DeeployTest/testRunner_siracusa_mchandma.py create mode 100644 DeeployTest/testRunner_snitch_dma.py create mode 100644 DeeployTest/testUtils/dmaUtils.py create mode 100644 DeeployTest/testUtils/tilingUtils.py delete mode 100644 TargetLibraries/PULPOpen/inc/dory_dma.h delete mode 100644 TargetLibraries/PULPOpen/inc/mchan.h create mode 100644 TargetLibraries/PULPOpen/inc/mchan_siracusa.h create mode 100644 TargetLibraries/PULPOpen/inc/mchan_v6.h create mode 100644 TargetLibraries/PULPOpen/inc/mchan_v7.h delete mode 100644 TargetLibraries/PULPOpen/src/dory_dma.c diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4f2c5a4919..5415a4a251 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -986,6 +986,24 @@ jobs: python testRegexMatching.py shell: bash + deeploy-test-dmas: + runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} + needs: select-docker-image-and-runner + container: + image: ${{ needs.select-docker-image-and-runner.outputs.image }} + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Build Deeploy + run: pip install -e . + - name: Run Test + run: | + cd DeeployTest + python testDmas.py + shell: bash + linting: runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} needs: select-docker-image-and-runner diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e056c0213..4a9764f227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,20 +2,52 @@ This file contains the changelog for the Deeploy project. The changelog is divided into sections based on the version of the project. Each section contains a list of pull requests, features, changes, fixes, and removals that were made in that version. ## Unreleased (Planned Release Target: v0.2.1) + ### List of Pull Requests - Change order of typeMatching entries [#68](https://github.com/pulp-platform/Deeploy/pull/68) - Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) +- Refactor tiling code generation [#105](https://github.com/pulp-platform/Deeploy/pull/105) ### Added - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough - Added a `testTypeInferenceDifferentTypes` test case to validate type inference for different input types - Added `_mangleNodeNames` function to avoid duplicate node mappings - Output Docker image digests per platform (`amd64`, `arm64`) after build, which is used to construct the multi-arch Docker manifest. This preventes registry clutter caused by unnecessary per-architecture Docker tags. +- AsyncDma abstraction of DMA's +- test runner per DMA and a script that tests all the DMA's +- generic Single/DoubleBufferingTilingCodeGeneration classes +- TilingVariableReplacementUpdate class that updates the variable replacement refs +- TilingHoistingMixIn class that encapsulates all the hoisting helper functions of tiling +- sorting of input memory allocations to allow references that live in the same memory level as the memory they are referencing +- a function that tests the tiling solution for correctness which currently only tests buffer allocation for byte alignment +- IntrospectiveCodeTransformation: `_indexPointer()`, `indexVars()`, `dereferenceVars()`. The `*Vars` functions index/dereference a list of variables (useful for tiling) +- NetworkContext: `unravelReference()` that unravels a `_ReferenceBuffer` until the base buffer +- NetworkContext: `is_object()` - helper function that determines whether the string represents a name of a local or global object +- NetworkContext: `is_buffer()` - helper function that determines whether the string represents a name of a buffer +- missing checks for environment variables +- `_permuteHyperRectangle` helper function ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. +- mchan HAL is now reduced to bare-bones +- refactor of the IntrospectiveCodeTransformation to work on the Mako template +- refactor of memory allocation code transformation passes +- _ReferenceBuffer accepts an optional `offset` argument to offset the reference +- NetworkContext: `hoistReference` - accepts the actual buffer as reference instead of name, accepts shape, offset, and override_type arguments, and returns the actual buffer, not its name +- `_mangleNodeRep` -> `_mangleOpRepr` - the canonical name we use is `OperatorRepresentation`. `NodeRep` and `ParseDict` are old iterations of the name. +- rename of permutation functions to follow this convention: `permute` is an action that permutes something, `permutation` is a function that generates a permutation +- `_permuteList` to just `_permute` +- removed manual buffer name mangling since we do it in the ExecutionBlock generate() function, simplifies templates +- we now check that buffer shapes/hyperrectangles/tiling ranks match which required changing a few `serializeTilingSolution` functions to preserve the same shape rank +- big refactor of the code generation part of the TilingExtension and needed changes to PULPOpen and Snitch due to it +- PULPClusterTilingSB and PULPClusterTilingDB now allow for transfers of any rank (dimensionality) +- PULP's final output diff is now calculated as absolute error, instead of just subtraction +- common code generation code between testMVP/generateNetwork/... was extracted into a single `generateTestNetwork` function +- in some functions, instead of passing the name of a buffer, the actual buffer is just passed +- tile function allows overriding the optimizer with external tilingSolution and memoryMap +- refactor of the permutation functions for clarity ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon @@ -23,6 +55,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ### Removed - Delete outdated and unused `.gitlab-ci.yml` file +- dory_dma.c and dory_dma.h ## Release v0.2.0 (2025-07-08) [#103](https://github.com/pulp-platform/Deeploy/pull/103) This release containing major architectural changes, new platform support, enhanced simulation workflows, floating-point kernel support, training infrastructure for CCT models, memory allocation strategies, and documentation improvements. diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py index b137266de6..8c1786dd5b 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py @@ -109,7 +109,7 @@ def _generateClosureStruct(self, ctxt: NetworkContext, executionBlock: Execution closureStruct: Dict[str, Union[Pointer, Immediate, Struct]] = {} makoDynamicReferences = self.extractDynamicReferences(ctxt, executionBlock, True) - for arg in list(dict.fromkeys(makoDynamicReferences)): + for arg in makoDynamicReferences: ref = ctxt.lookup(arg) if isinstance(ref, TransientBuffer): closureStructArgsType[ctxt._mangle(arg)] = PointerClass(VoidType) @@ -202,7 +202,7 @@ def _generateClosureStruct(self, ctxt: NetworkContext, executionBlock: Execution # Add closure struct info to operatorRepresentation closureStructArgsType = {} closureStruct = {} - makoDynamicReferences = self.extractDynamicReferences(ctxt, executionBlock, True) + makoDynamicReferences = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True) filteredMakoDynamicReferences = [] diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py index acdcc0d09c..51d7dba617 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py @@ -23,16 +23,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy import types from typing import Dict, List import mako.codegen as codegen from mako.lexer import Lexer -from mako.parsetree import Expression, TemplateNode +from mako.parsetree import Expression, TemplateNode, Text +from mako.template import Template from Deeploy.AbstractDataTypes import Pointer, Struct -from Deeploy.DeeployTypes import ExecutionBlock, NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer +from Deeploy.DeeployTypes import ExecutionBlock, NetworkContext, OperatorRepresentation, VariableBuffer _NULL: str = "NULL" @@ -42,65 +42,76 @@ class IntrospectiveCodeTransformationMixIn(): parseTreeDict: Dict[int, TemplateNode] = {} @staticmethod - def _generateParseTree(template: NodeTemplate) -> TemplateNode: - return Lexer(template.template._source).parse() + def _generateParseTree(template: Template) -> TemplateNode: + return Lexer(template._source).parse() @staticmethod - def _reconstructCode(template: NodeTemplate, node: TemplateNode): - - def fixupParseTree(parseTree: TemplateNode) -> TemplateNode: - nodes = [] - prevLine = 0 - prevPos = 0 - for node in parseTree.nodes: - - newNode = copy.copy(node) - offset = len(node.source) - - # Expression contain the actual expression + the symbols "${}", i.e. 3 offset symbols - if isinstance(newNode, Expression): - offset += 3 + def _reconstructCode(template: Template, node: TemplateNode) -> Template: + lexer = Lexer(template._source) + source = codegen.compile( + node, + template.uri, + None, + default_filters = template.default_filters, + buffer_filters = template.buffer_filters, + imports = template.imports, + future_imports = template.future_imports, + source_encoding = lexer.encoding, + generate_magic_comment = True, + strict_undefined = template.strict_undefined, + enable_loop = template.enable_loop, + reserved_names = template.reserved_names, + ) + module = types.ModuleType(template.module_id) + code = compile(source, template.module_id, "exec") + exec(code, module.__dict__, module.__dict__) - prevPos = prevPos + offset + template._code = code + template.module = module + template.callable_ = template.module.render_body + return template - if prevLine != node.lineno: - prevPos = node.pos + @staticmethod + def _indexPointer(parseTree: TemplateNode, ptrName: str, index: str) -> TemplateNode: + indexes = [i for i, node in enumerate(parseTree.nodes) if isinstance(node, Expression) and node.text == ptrName] - newNode.pos = prevPos - prevLine = node.lineno + for offset, idx in enumerate(indexes): + bracketOpen = Text("[", source = "[", lineno = 0, pos = 0, filename = None) + indexExpr = Expression(index, '', source = index, lineno = 0, pos = 0, filename = None) + bracketClose = Text("]", source = "]", lineno = 0, pos = 0, filename = None) + parseTree.nodes.insert(idx + 3 * offset + 1, bracketOpen) + parseTree.nodes.insert(idx + 3 * offset + 2, indexExpr) + parseTree.nodes.insert(idx + 3 * offset + 3, bracketClose) - nodes.append(newNode) + return parseTree - parseTree.nodes = nodes + @staticmethod + def indexVars(template: Template, varNames: List[str], index: str) -> None: + if len(varNames) == 0: + return + parseTree = IntrospectiveCodeTransformationMixIn._generateParseTree(template) + for name in varNames: + parseTree = IntrospectiveCodeTransformationMixIn._indexPointer(parseTree, name, index) + IntrospectiveCodeTransformationMixIn._reconstructCode(template, parseTree) - return parseTree + @staticmethod + def _dereferencePointer(parseTree: TemplateNode, ptrName: str) -> TemplateNode: + indexes = [i for i, node in enumerate(parseTree.nodes) if isinstance(node, Expression) and node.text == ptrName] - node = fixupParseTree(node) + for offset, idx in enumerate(indexes): + text = Text("*", source = "*", lineno = 0, pos = 0, filename = None) + parseTree.nodes.insert(idx + offset, text) - temp = template.template - lexer = Lexer(temp._source) - source = codegen.compile( - node, - temp.uri, - None, - default_filters = temp.default_filters, - buffer_filters = temp.buffer_filters, - imports = temp.imports, - future_imports = temp.future_imports, - source_encoding = lexer.encoding, - generate_magic_comment = True, - strict_undefined = temp.strict_undefined, - enable_loop = temp.enable_loop, - reserved_names = temp.reserved_names, - ) - module = types.ModuleType(temp.module_id) - code = compile(source, temp.module_id, "exec") - exec(code, module.__dict__, module.__dict__) + return parseTree - temp._code = code - temp.module = module - temp.callable_ = temp.module.render_body - template.template = temp + @staticmethod + def dereferenceVars(template: Template, varNames: List[str]) -> None: + if len(varNames) == 0: + return + parseTree = IntrospectiveCodeTransformationMixIn._generateParseTree(template) + for name in varNames: + parseTree = IntrospectiveCodeTransformationMixIn._dereferencePointer(parseTree, name) + IntrospectiveCodeTransformationMixIn._reconstructCode(template, parseTree) def extractDynamicReferences(self, ctxt: NetworkContext, @@ -112,7 +123,7 @@ def extractDynamicReferences(self, for codeSnippet in executionBlock.codeSnippets: template, operatorRepresentation = codeSnippet.template, codeSnippet.operatorRepresentation - newRefs = self._extractDynamicExpressions(ctxt, operatorRepresentation, template, unrollStructs, + newRefs = self._extractDynamicExpressions(ctxt, operatorRepresentation, template.template, unrollStructs, includeGobalReferences) makoDynamicReferences += newRefs @@ -132,11 +143,10 @@ def _fixCtxtOrdering(ctxt: NetworkContext, nameList: List[str]) -> List[str]: def _extractDynamicExpressions(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - template: NodeTemplate, + template: Template, unrollStructs = False, includeGobalReferences = False): - - codeHash = hash(template.template._source) + codeHash = hash(template._source) if codeHash in self.parseTreeDict.keys(): makoParseTree = self.parseTreeDict[codeHash] @@ -146,60 +156,43 @@ def _extractDynamicExpressions(self, self.parseTreeDict[codeHash] = makoParseTree # Filter parsing tree for expressions - makoExpressions = [node.text for node in makoParseTree.nodes if type(node) == Expression] + makoExpressions = [node.text for node in makoParseTree.nodes if isinstance(node, Expression)] - # Filter expressions for local variables contained in operatorRepresentation - makoLocalReferences = [ - node for node in makoExpressions - if ((node in operatorRepresentation) and type(operatorRepresentation[node]) == str and ( - operatorRepresentation[node] in ctxt.localObjects.keys())) + # Filter represented expressions + representedExpressions = [ + operatorRepresentation[expr] for expr in makoExpressions if expr in operatorRepresentation ] - # Filter expressions for global variables contained in operatorRepresentation - makoGlobalReferences = [ - node for node in makoExpressions - if ((node in operatorRepresentation) and type(operatorRepresentation[node]) == str and ( - operatorRepresentation[node] in ctxt.globalObjects.keys())) - ] + # Filter buffers from expressions + references = [expr for expr in representedExpressions if ctxt.is_buffer(expr)] + + if unrollStructs: + + def _unrollStructReferences(val: Struct) -> List[str]: + assert isinstance(val, Struct) + # Recursively unroll struct references + structReferences = [] + for field in val.value.values(): + if isinstance(field, Struct): + structReferences += _unrollStructReferences(field) + elif isinstance(field, Pointer) and field.referenceName != _NULL: + structReferences.append(field.referenceName) + return structReferences + + # Unroll local struct references + for ref in references: + if hasattr(ctxt.lookup(ref), "structDict"): + references += _unrollStructReferences(ctxt.lookup(ref).structDict) - def _unrollStructReferences(val) -> List[str]: - # Unroll struct references - structReferences = [] - if isinstance(val, Struct): - for key, _type in val.value.items(): - if isinstance(_type, Struct): - structReferences += _unrollStructReferences(val.value[key]) - elif isinstance(_type, Pointer) and val.value[key].referenceName != _NULL: - structReferences.append(val.value[key].referenceName) - return structReferences - - # Unroll local struct references - localReferences = [] - localStructReferences = [] - for ref in makoLocalReferences: - localReferences.append(operatorRepresentation[ref]) - if unrollStructs: - if ctxt.is_local(operatorRepresentation[ref]) and hasattr(ctxt.lookup(operatorRepresentation[ref]), - "structDict"): - localStructReferences += _unrollStructReferences( - ctxt.lookup(operatorRepresentation[ref]).structDict) - - # Unroll global struct references - globalReferences = [] - globalStructReferences = [] - for ref in makoGlobalReferences: - globalReferences.append(operatorRepresentation[ref]) - if unrollStructs: - if ctxt.is_global(operatorRepresentation[ref]) and hasattr(ctxt.lookup(operatorRepresentation[ref]), - "structDict"): - globalStructReferences += _unrollStructReferences( - ctxt.lookup(operatorRepresentation[ref]).structDict) + # Filter expressions for local variables contained in operatorRepresentation + localReferences = [ref for ref in references if ctxt.is_local(ref)] + + # Filter expressions for global variables contained in operatorRepresentation + globalReferences = [ref for ref in references if ctxt.is_global(ref)] # Filter for dynamically allocated tensors - dynamicLocalReferences = [ref for ref in localReferences + localStructReferences if ctxt.lookup(ref)._deploy] - dynamicGlobalReferences = [ - ref for ref in globalReferences + globalStructReferences if isinstance(ctxt.lookup(ref), VariableBuffer) - ] + dynamicLocalReferences = [ref for ref in localReferences if ctxt.lookup(ref)._deploy] + dynamicGlobalReferences = [ref for ref in globalReferences if isinstance(ctxt.lookup(ref), VariableBuffer)] if includeGobalReferences: return dynamicLocalReferences + dynamicGlobalReferences diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py index b95d31a01b..2293ded8e5 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py @@ -30,7 +30,7 @@ from Deeploy.CommonExtensions.CodeTransformationPasses.IntrospectiveCodeTransformation import \ IntrospectiveCodeTransformationMixIn from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, \ - NodeTemplate, StructBuffer, TransientBuffer, _NoVerbosity + NodeTemplate, StructBuffer, TransientBuffer, VariableBuffer, _NoVerbosity, _ReferenceBuffer class _ArgStructAllocateTemplate(NodeTemplate): @@ -77,112 +77,84 @@ def apply(self, class MemoryManagementGeneration(CodeTransformationPass, IntrospectiveCodeTransformationMixIn): - def __init__(self, memoryHierarchyRegex: Optional[str] = None): + def __init__(self, memoryLevelRegex: Optional[str] = None): super().__init__() - if memoryHierarchyRegex is not None: - self.regex = re.compile(memoryHierarchyRegex) + if memoryLevelRegex is not None: + self.regex = re.compile(memoryLevelRegex) else: self.regex = None - def _matchesRegex(self, ctxt: NetworkContext, key: str) -> bool: - _buffer = ctxt.lookup(key) - + def is_memory_level(self, buffer: VariableBuffer) -> bool: if self.regex is None: - return not hasattr(_buffer, "_memoryLevel") - - if not hasattr(_buffer, "_memoryLevel"): - return False - - ret = self.regex.findall(ctxt.lookup(key)._memoryLevel) - return ret != [] - - def _extractTransientBuffers(self, ctxt: NetworkContext, name: str) -> List[str]: - names = [] - - for key, _buffer in ctxt.localObjects.items(): - if isinstance(_buffer, TransientBuffer) and name in _buffer._users: - names.append(key) - - filteredNames = [key for key in names if self._matchesRegex(ctxt, key)] - - return filteredNames + return not hasattr(buffer, "_memoryLevel") + else: + return hasattr(buffer, "_memoryLevel") and self.regex.fullmatch(buffer._memoryLevel) is not None - def _getOutputNames(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str) -> List[str]: - outputs = [] - references = self.extractDynamicReferences(ctxt, executionBlock, True) - localKeys = [key for key in references if ctxt.is_local(key)] + @staticmethod + def is_final_input(buffer: VariableBuffer, nodeName: str) -> bool: + return not isinstance(buffer, (StructBuffer, TransientBuffer)) and \ + len(buffer._users) > 0 and nodeName == buffer._users[-1] - filteredKeys = [key for key in localKeys if self._matchesRegex(ctxt, key)] + @staticmethod + def is_output(buffer: VariableBuffer, nodeName: str) -> bool: + return not isinstance(buffer, (StructBuffer, TransientBuffer)) and nodeName not in buffer._users - for key in filteredKeys: - _buffer = ctxt.lookup(key) - if isinstance(_buffer, (StructBuffer, TransientBuffer)): - continue - if name not in _buffer._users: - outputs.append(_buffer.name) + @staticmethod + def is_transient(buffer: VariableBuffer, nodeName: str) -> bool: + return isinstance(buffer, TransientBuffer) and nodeName in buffer._users - return list(dict.fromkeys(outputs)) + @staticmethod + def topologicallySortBuffers(buffers: List[VariableBuffer]) -> List[VariableBuffer]: + sortedBuffers = [] + unsortedBufferNames = [buff.name for buff in buffers] + lastLen = len(unsortedBufferNames) - def _getFinalInputNames(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str) -> List[str]: - inputs = [] - references = self.extractDynamicReferences(ctxt, executionBlock, True) - localKeys = [key for key in references if ctxt.is_local(key)] + while len(unsortedBufferNames) > 0: + for buffer in buffers: + if isinstance(buffer, _ReferenceBuffer) and buffer._referenceName in unsortedBufferNames: + continue - filteredKeys = [key for key in localKeys if self._matchesRegex(ctxt, key)] + sortedBuffers.append(buffer) + unsortedBufferNames.remove(buffer.name) - for key in filteredKeys: - _buffer = ctxt.lookup(key) - if isinstance(_buffer, (StructBuffer, TransientBuffer)) or _buffer._users == []: - continue - if name == _buffer._users[-1]: - inputs.append(_buffer.name) + assert len(unsortedBufferNames) != lastLen, f"Circular reference detected." + lastLen = len(unsortedBufferNames) - return list(dict.fromkeys(inputs)) + return sortedBuffers def apply(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: + references = self.extractDynamicReferences(ctxt, + executionBlock, + unrollStructs = True, + includeGobalReferences = False) + localBuffers = [ctxt.localObjects[ref] for ref in references] + memoryLevelBuffers = [buff for buff in localBuffers if self.is_memory_level(buff)] - outputNames = self._getOutputNames(ctxt, executionBlock, name) - inputNames = self._getFinalInputNames(ctxt, executionBlock, name) - transientBuffers = self._extractTransientBuffers(ctxt, name) + transients = [buff for buff in memoryLevelBuffers if self.is_transient(buff, name)] + outputs = [buff for buff in memoryLevelBuffers if self.is_output(buff, name)] + inputs = [buff for buff in memoryLevelBuffers if self.is_final_input(buff, name)] # We have to allocate the output buffers, unless they are global - - for buffer in list(reversed(outputNames)) + transientBuffers: - # Extract buffer info from context - nb = ctxt.lookup(buffer) - - # Check that it was not already allocated - assert ctxt.localObjects[nb.name]._live == False, f"Tried to allocate already live buffer {nb.name}" - - # Mark it as live - ctxt.localObjects[nb.name]._live = True - - # Add the allocation code to the execution block - executionBlock.addLeft(nb.allocTemplate, nb._bufferRepresentation()) - - for buffer in inputNames + transientBuffers: - # Extract buffer info from context - nb = ctxt.lookup(buffer) - - # Check that it was not already deallocated - assert ctxt.localObjects[nb.name]._live == True, f"Tried to deallocate already dead buffer {nb.name}" - - # Mark it as dead (not useful anymore) - ctxt.localObjects[nb.name]._live = False - - # Check for live ancestors (buffers that this is an alias of, that are still live), - # and add the deallocation code to the execution block if none found - if not nb.has_live_ancestors(ctxt = ctxt): - executionBlock.addRight(nb.deallocTemplate, nb._bufferRepresentation()) + for buffer in reversed(self.topologicallySortBuffers(outputs + transients)): + assert buffer._live == False, f"Tried to allocate already live buffer {buffer.name}" + buffer._live = True + executionBlock.addLeft(buffer.allocTemplate, buffer._bufferRepresentation()) + + for buffer in inputs + transients: + assert buffer._live == True, f"Tried to deallocate already dead buffer {buffer.name}" + buffer._live = False + # Don't deallocate if it's an alias of a live buffer + if not buffer.has_live_ancestors(ctxt = ctxt): + executionBlock.addRight(buffer.deallocTemplate, buffer._bufferRepresentation()) return ctxt, executionBlock -class MemoryPassthroughGeneration(MemoryManagementGeneration, IntrospectiveCodeTransformationMixIn): +class MemoryPassthroughGeneration(MemoryManagementGeneration): def __init__(self, memoryHierarchyRegex: Optional[str] = None): super().__init__(memoryHierarchyRegex) @@ -192,22 +164,23 @@ def apply(self, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: - - outputNames = self._getOutputNames(ctxt, executionBlock, name) - inputNames = self._getFinalInputNames(ctxt, executionBlock, name) - transientBuffers = self._extractTransientBuffers(ctxt, name) - - # We have to allocate the output buffers, unless they are global - for buffer in outputNames + transientBuffers: - nb = ctxt.lookup(buffer) - - assert ctxt.localObjects[nb.name]._live == False, f"Tried to allocate already live buffer {nb.name}" - ctxt.localObjects[nb.name]._live = True - - for buffer in inputNames + transientBuffers: - nb = ctxt.lookup(buffer) - - assert ctxt.localObjects[nb.name]._live == True, f"Tried to deallocate already dead buffer {nb.name}" - ctxt.localObjects[nb.name]._live = False + references = self.extractDynamicReferences(ctxt, + executionBlock, + unrollStructs = True, + includeGobalReferences = False) + localBuffers = [ctxt.localObjects[ref] for ref in references] + memoryLevelBuffers = [buff for buff in localBuffers if self.is_memory_level(buff)] + + transients = [buff for buff in memoryLevelBuffers if self.is_transient(buff, name)] + outputs = [buff for buff in memoryLevelBuffers if self.is_output(buff, name)] + inputs = [buff for buff in memoryLevelBuffers if self.is_final_input(buff, name)] + + for buffer in outputs + transients: + assert buffer._live == False, f"Tried to allocate already live buffer {buffer.name}" + buffer._live = True + + for buffer in inputs + transients: + assert buffer._live == True, f"Tried to deallocate already dead buffer {buffer.name}" + buffer._live = False return ctxt, executionBlock diff --git a/Deeploy/CommonExtensions/DataTypes.py b/Deeploy/CommonExtensions/DataTypes.py index f88eef2851..050e5b44ff 100644 --- a/Deeploy/CommonExtensions/DataTypes.py +++ b/Deeploy/CommonExtensions/DataTypes.py @@ -23,7 +23,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Tuple, Type +from typing import Iterable, Tuple, Type, Union + +import numpy.typing as npt from Deeploy.AbstractDataTypes import FloatImmediate, IntegerImmediate @@ -111,4 +113,32 @@ class float64_t(FloatImmediate): *UnsignedIntegerDataTypes, ), key = lambda _type: _type.typeWidth)) -FloatDataTypes: Tuple[Type[FloatImmediate], ...] = (bfloat16_t, float16_t, float32_t, float64_t) \ No newline at end of file +FloatDataTypes: Tuple[Type[FloatImmediate], ...] = (bfloat16_t, float16_t, float32_t, float64_t) + + +def minimalIntegerType(value: Union[int, Iterable[int], npt.NDArray]) -> Type[IntegerImmediate]: + # Sort data types by typeWidth and signedness (unsigned types go first) + sorted_types = sorted( + IntegerDataTypes, + key = lambda t: (t.typeWidth, t.typeMin < 0), + ) + + for _type in sorted_types: + if _type.checkValue(value): + return _type + + raise RuntimeError(f"Couldn't find appropriate integer type for value: {value}") + + +def minimalFloatType(value: Union[float, Iterable[float], npt.NDArray]) -> Type[FloatImmediate]: + # Sort data types by typeWidth + sorted_types = sorted( + FloatDataTypes, + key = lambda t: t.typeWidth, + ) + + for _type in sorted_types: + if _type.checkValue(value): + return _type + + raise RuntimeError(f"Couldn't find appropriate float type for value: {value}") diff --git a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py index c3887ab54d..4e95f9855b 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py @@ -24,7 +24,7 @@ # limitations under the License. from functools import partial -from typing import Iterable, List, Optional, Sequence, Tuple, Union +from typing import Iterable, List, Optional, Sequence, Tuple, TypeVar, Union import numpy as np import onnx_graphsurgeon as gs @@ -32,6 +32,7 @@ from Deeploy.CommonExtensions.OptimizationPasses.Matchers import Match from Deeploy.CommonExtensions.OptimizationPasses.PassClasses import ReplaceSequentialPatternPass, SequentialPass, \ contextagnostic +from Deeploy.TilingExtension.TilingCodegen import HyperRectangle def _createReshape(tensorIn: gs.Tensor, @@ -106,59 +107,53 @@ def _prependSqueezeDims(tensor: gs.Tensor, name: str, axis: Union[int, Sequence[ # Permute (0,1,2,3,...,N-2,N-1) -> (0,1,2,3,...,N-1,N-2) -def _permuteLastTwoDims(length: int) -> List[int]: - outList = list(range(length)) - tmp = outList[-1] - outList[-1] = outList[-2] - outList[-2] = tmp - return outList +def _permutationLastTwoDims(N: int) -> List[int]: + assert N >= 2, "N needs to be larger then 2" + return list(range(N - 2)) + [N - 1, N - 2] # Permute (0,1,2,3,...,N-1) -> (0,2,3,...,N-1,1) -def _permuteNCHWtoNHWC(length: int) -> List[int]: - outList = list(range(length)) - outList.remove(1) - outList.append(1) - return outList +def _permutationNCHWtoNHWC(N: int) -> List[int]: + assert N >= 3, "N needs to be larger then 3 for this to make any sense" + return [0] + list(range(2, N)) + [1] # Permute (0,1,2,3,...,N-1) -> (0,N-1,1,2,3,...,N-2) -def _permuteNHWCtoNCHW(length: int) -> List[int]: - outList = list(range(length)) - outList.remove(length - 1) - outList.insert(1, length - 1) - return outList +def _permutationNHWCtoNCHW(N: int) -> List[int]: + assert N >= 3, "N needs to be larger then 3 for this to make any sense" + return [0, N - 1] + list(range(1, N - 1)) # Calculate permutation q = p^(-1) s.t. q(p(i)) = i def _invertPermutation(permutation: List[int]) -> List[int]: - tuples = [] - for idx, i in enumerate(permutation): - tuples.append((i, idx)) - sortedTuples = sorted(tuples, key = lambda x: x[0]) - outPermutation = [] - for i in sortedTuples: - outPermutation.append(i[1]) - return outPermutation + inverse = [0] * len(permutation) + for idx, permIdx in enumerate(permutation): + inverse[permIdx] = idx + return inverse -def _permuteList(inputList: List, permutation: List[int]): - assert len(inputList) == len(permutation), "Permuted list and permutation must have equal length!" - outList = [] - for i in permutation: - outList.append(inputList[i]) - return outList +T = TypeVar('T') + + +def _permute(_list: Sequence[T], permutation: Sequence[int]) -> List[T]: + assert len(_list) == len(permutation), "Permuted list and permutation must have equal length!" + return [_list[i] for i in permutation] + + +def _permuteHyperRectangle(rect: HyperRectangle, permutation: List[int]) -> HyperRectangle: + assert len(rect.dims) == len(permutation), "Permutation list and HyperRectangle must have equal dimensionality!" + return HyperRectangle(tuple(_permute(rect.offset, permutation)), tuple(_permute(rect.dims, permutation))) def _prependTransposeNode(anchor: gs.Variable, nodeName: str, permutation: Iterable[int], - invert: bool = False) -> (gs.Node, gs.Variable): + invert: bool = False) -> Tuple[gs.Node, gs.Variable]: if invert: - outShape = _permuteList(anchor.shape, _invertPermutation(permutation)) + outShape = _permute(anchor.shape, _invertPermutation(permutation)) else: - outShape = _permuteList(anchor.shape, permutation) + outShape = _permute(anchor.shape, permutation) anchorTransposeInput = gs.Variable(nodeName + "_Out", dtype = np.float32, shape = outShape) anchorTransposeNode = gs.Node(name = nodeName, @@ -176,9 +171,9 @@ def _appendTransposeNode(anchor: gs.Variable, invert: bool = False) -> (gs.Node, gs.Variable): if invert: - outShape = _permuteList(anchor.shape, _invertPermutation(permutation)) + outShape = _permute(anchor.shape, _invertPermutation(permutation)) else: - outShape = _permuteList(anchor.shape, permutation) + outShape = _permute(anchor.shape, permutation) anchorTransposeOutput = gs.Variable(nodeName + "_In", dtype = np.float32, shape = outShape) anchorTransposeNode = gs.Node(name = nodeName, @@ -210,7 +205,7 @@ def _transposeMatMulInputs_fun(graph: gs.Graph, match: Match, name: str): # Prepend transpose on A if it's transposed if gemmNode.attrs['transA'] != 0: anchorTransposeNode, anchorTransposeOutput = _appendTransposeNode(inputA, name + "_A", - _permuteLastTwoDims(len(inputA.shape))) + _permutationLastTwoDims(len(inputA.shape))) gemmNode.inputs[0] = anchorTransposeOutput gemmNode.attrs['transA'] = 0 graph.nodes.append(anchorTransposeNode) @@ -218,7 +213,7 @@ def _transposeMatMulInputs_fun(graph: gs.Graph, match: Match, name: str): # Prepend transpose on B if it's not transposed if gemmNode.attrs['transB'] != 1: anchorTransposeNode, anchorTransposeOutput = _appendTransposeNode(inputB, name + "_B", - _permuteLastTwoDims(len(inputB.shape))) + _permutationLastTwoDims(len(inputB.shape))) gemmNode.inputs[1] = anchorTransposeOutput gemmNode.attrs['transB'] = 1 graph.nodes.append(anchorTransposeNode) @@ -256,8 +251,8 @@ def _NCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_f inputNode = opNode.inputs[0] outputNode = opNode.outputs[0] - inPermute = _permuteNCHWtoNHWC(len(inputNode.shape)) - outPermute = _permuteNHWCtoNCHW(len(outputNode.shape)) + inPermute = _permutationNCHWtoNHWC(len(inputNode.shape)) + outPermute = _permutationNHWCtoNCHW(len(outputNode.shape)) inputTransposeNode, inputTransposeOutput = _appendTransposeNode(inputNode, name + "_TransposeIn", inPermute) outputTransposeNode, outputTransposeInput = _prependTransposeNode(outputNode, @@ -376,8 +371,8 @@ def _PULPDWNCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_chan inputNode = opNode.inputs[0] outputNode = opNode.outputs[0] - inPermute = _permuteNCHWtoNHWC(len(inputNode.shape)) - outPermute = _permuteNHWCtoNCHW(len(outputNode.shape)) + inPermute = _permutationNCHWtoNHWC(len(inputNode.shape)) + outPermute = _permutationNHWCtoNCHW(len(outputNode.shape)) outputTransposeNode, outputTransposeInput = _prependTransposeNode(outputNode, name + "_TransposeOut", @@ -534,7 +529,7 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): # If transA is set then the matrix is of shape [B x K x M] and it needs to be transposed, otherwise its shape is [B x M x K] if 'transA' in requantizedGemm.attrs and requantizedGemm.attrs['transA'] == 1: - matrixATransposeNode, matrixA = _appendTransposeNode(matrixA, name, _permuteLastTwoDims(len(matrixA.shape))) + matrixATransposeNode, matrixA = _appendTransposeNode(matrixA, name, _permutationLastTwoDims(len(matrixA.shape))) graph.nodes.append(matrixATransposeNode) # Align dimensions for convolution @@ -551,7 +546,7 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): # If transB is set then the matrix is of shape [N x K] and it doesn't need to be transposed, otherwise its shape is [K x N] and it has to be transposed if not 'transB' in requantizedGemm.attrs or requantizedGemm.attrs['transB'] == 0: # matrixBTransposed, shape [N x K] - matrixBTransposeNode, matrixB = _appendTransposeNode(matrixB, name, _permuteLastTwoDims(len(matrixB.shape))) + matrixBTransposeNode, matrixB = _appendTransposeNode(matrixB, name, _permutationLastTwoDims(len(matrixB.shape))) graph.nodes.append(matrixBTransposeNode) # pwWeight, shape [N x 1 x 1 x K] matrixBExpandDimsNode, pwWeight = _appendExpandDims(matrixB, name, axis = (1, 2)) diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index c7392a6786..f3281f1759 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -35,7 +35,7 @@ from collections import OrderedDict, deque from dataclasses import dataclass from functools import reduce -from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union +from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Set, Tuple, Type, TypeVar, Union import mako import numpy as np @@ -118,7 +118,8 @@ def __init__(self, templateStr: str): """ self.template = _Template(templateStr, strict_undefined = True) - self.subTemplates = {} + self.subTemplates: Dict[str, Tuple[NodeTemplate, Callable[[NetworkContext, OperatorRepresentation], + Tuple[NetworkContext, OperatorRepresentation]]]] = {} self.subTemplateGenerators = {} def internalSize(self) -> int: @@ -535,22 +536,33 @@ class _ReferenceBuffer(VariableBuffer): """Helper class to hoist references to pre-established pointers; this is used most frequently in tiling to express an offset with respect to input or output tensors """ - allocTemplate = NodeTemplate("${type.typeName} ${name} = (${type.typeName}) ${objectName};") + allocTemplate = NodeTemplate("""\\ + % if offset is None: + ${type.typeName} ${name} = (${type.typeName}) ${referenceName};\\ + % else: + ${type.typeName} ${name} = (${type.typeName}) ${referenceName} + ${offset};\\ + % endif + """) deallocTemplate = NodeTemplate("") initTemplate = NodeTemplate("") - def __init__(self, name: str = '', shape = [1], reference: Optional[VariableBuffer] = None): - - assert reference is not None, "Can't have a reference to None!" - + def __init__(self, + name: str, + reference: VariableBuffer, + shape: Tuple[int, ...] = (1,), + offset: Optional[Union[int, str, VariableBuffer]] = None): super().__init__(name, shape) - self._referencedBuffer = str(reference._instance) self._referenceName = reference.name + if isinstance(offset, VariableBuffer): + self._offset = offset.name + else: + self._offset = offset def _bufferRepresentation(self) -> Dict: - rep = super()._bufferRepresentation() - rep['objectName'] = self._referencedBuffer - return rep + repr = super()._bufferRepresentation() + repr['referenceName'] = self._referenceName + repr['offset'] = self._offset + return repr class NetworkContext(): @@ -573,13 +585,13 @@ def __init__(self, self.TransientBuffer = transientBuffer self.name = name - def dealiasBuffer(self, referenceName: str) -> str: - """Function to unravel reference instantiated in _ReferenceBuffer objects until the underlying VariableBuffer's name is returned + def dealiasBuffer(self, name: str) -> str: + """Function to find the underlying aliased VariableBuffer Parameters ---------- - referenceName : str - Name of the _ReferenceBuffer to unravel + name: str + Name of the VariableBuffer to dealias Returns ------- @@ -589,25 +601,42 @@ def dealiasBuffer(self, referenceName: str) -> str: Raises ------ Exception - Raises an Exception if references are circular, i.e. there - is no underlying VariableBuffer + Raises an Exception if aliases are circular """ - _buffer = self.lookup(referenceName) - if not hasattr(_buffer, "_alias"): - return referenceName - seenAliases: Set[str] = set() + alias = self.lookup(name) + while hasattr(alias, "_alias"): + seenAliases.add(alias.name) + alias = self.lookup(alias._alias) + assert alias.name not in seenAliases, "Circular aliasing detected!" + return alias.name - alias = _buffer._alias - while hasattr(self.lookup(alias), "_alias"): - seenAliases.add(alias) - alias = self.lookup(alias)._alias + def unravelReference(self, ref: VariableBuffer) -> VariableBuffer: + """Function to find the underlying referenced VariableBuffer + + Parameters + ---------- + ref : VariableBuffer + Buffer to unravel - if alias in seenAliases: - raise Exception("Circular aliasing detected!") + Returns + ------- + str + Name of the original VariableBuffer that was referenced - return alias + Raises + ------ + Exception + Raises an Exception if references are circular + + """ + seenRefs = set() + while isinstance(ref, _ReferenceBuffer): + seenRefs.add(ref.name) + ref = self.lookup(ref._referenceName) + assert ref.name not in seenRefs, "Circular reference found" + return ref def exportNetworkContext(self, folderPath: str, fileName: str): """Exports the NetworkContext as a pickled dictionary @@ -706,7 +735,7 @@ def _mangle(self, name: str, repr: bool = True) -> str: repStr = re.sub('\.', '_', self.name) + '_' + repStr return repStr - def add(self, obj: VariableBuffer, ctxt: str = 'local', _id: str = ""): + def add(self, obj: VariableBuffer, ctxt: Literal['local', 'global'] = 'local', _id: str = ""): """Adds a VariableBuffer object to the NetworkContext Parameters @@ -793,10 +822,7 @@ def is_global(self, name: str) -> bool: Returns true if the name matches with any global buffer """ - if name in self.globalObjects.keys(): - return True - else: - return False + return name in self.globalObjects def is_local(self, name: str) -> bool: """Checks whether a name is associated with a local buffer @@ -812,11 +838,42 @@ def is_local(self, name: str) -> bool: Returns ture if the name matches with any local buffer """ + return name in self.localObjects - if name in self.localObjects.keys(): - return True - else: + def is_object(self, value: Any) -> bool: + """Checks whether a value is an existing object name + + Parameters + ---------- + value : Any + Value to check + + Returns + ------- + bool + Returns ture if the value is an existing buffer name + + """ + return isinstance(value, str) and (self.is_local(value) or self.is_global(value)) + + def is_buffer(self, value: Any) -> bool: + """Checks whether a value is an existing buffer name + + Parameters + ---------- + value : Any + Value to check + + Returns + ------- + bool + Returns ture if the value is an existing buffer name + + """ + if not self.is_object(value): return False + obj = self.lookup(value) + return isinstance(obj, VariableBuffer) def hoistTransientBuffer(self, name: str, size: int) -> str: """Registers a new TransientBuffer in the local context @@ -901,48 +958,47 @@ def hoistConstantAndReference(self, constBuf: ConstantBuffer, pointerType: Type[ name of the registered _ReferenceBuffer """ - - name = constBuf.name constBuf._type = pointerType - self.add(constBuf, "global") + constBuf._instance = constBuf._type(constBuf.name, self) + ref = self.hoistReference(constBuf.name + "_ref", constBuf) + return ref.name - constBuf._instance = constBuf._type(name, self) - - refName = name + "_ref" - reference = self.hoistReference(name, refName) - - return refName - - def hoistReference(self, _reference: str, name: str) -> str: - """Helper function to register a _ReferenceBuffer to preexisting VariableBuffer + def hoistReference(self, + name: str, + reference: VariableBuffer, + shape: Tuple[int, ...] = (1,), + offset: Union[int, str, VariableBuffer] = 0, + override_type: Optional[Type[BaseType]] = None) -> _ReferenceBuffer: + """Helper function to register a _ReferenceBuffer to a preexisting VariableBuffer Parameters ---------- - _reference : str - Name of the VariableBuffer that should be referenced name : str - Name of the _ReferenceBuffer that should be registered + Name of the _ReferenceBuffer to register + reference : VariableBuffer + Referenced VariableBuffer + shape: Tuple[int, ...] + Shape of the _ReferenceBuffer + offset: Union[int, str, VariableBuffer] + Offset from the reference + override_type: Optional[Type[BaseType]] + Optional argument to override the reference type Returns ------- - str - Returns the name of the newly registered _ReferenceBuffer + _ReferenceBuffer + Returns the newly registered _ReferenceBuffer """ - - assert _reference != name, f"Reference name {_reference} cannot be the same as {name}" - assert not self.is_local(name), f"{name} is already in context!" - - _object = self.lookup(_reference) - - referenceBuffer = _ReferenceBuffer(name, reference = _object) - referenceBuffer._type = _object._type - - self.add(referenceBuffer, 'local') - referenceBuffer._instance = _object._type(name, ctxt = self) - - return name + ref = _ReferenceBuffer(name, reference, shape, offset) + if override_type is not None: + ref._type = PointerClass(override_type) + else: + ref._type = reference._type + self.add(ref, 'local') + ref._instance = ref._type(name, ctxt = self) + return ref def hoistConstant(self, node: gs.Node, name: str = '', _type: Optional[Type[Pointer]] = None) -> str: """Register a ConstantBuffer extracted directly from a graphsurgeon Node @@ -1470,17 +1526,16 @@ def hoisting(self, ctxt: NetworkContext, **kwargs) -> Tuple[NetworkContext, List return newCtxt, transientBuffers + contextBuffers @staticmethod - def _mangleNodeRep(ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation) -> OperatorRepresentation: - parseDict = {} + def _mangleOpRepr(ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation) -> OperatorRepresentation: + mangledOpRepr = {} for key, value in operatorRepresentation.items(): - if type(value) == str and (ctxt.is_local(value) or - ctxt.is_global(value)) and not isinstance(ctxt.lookup(value), GlobalDefinition): - parseDict[key] = ctxt._mangle(value) + if ctxt.is_buffer(value): + mangledOpRepr[key] = ctxt._mangle(value) else: - parseDict[key] = value + mangledOpRepr[key] = value - return parseDict + return mangledOpRepr def generate(self, ctxt: NetworkContext, **kwargs) -> str: """Generates the code for all registered NodeTemplates and joins it to construct a single snippet @@ -1499,7 +1554,7 @@ def generate(self, ctxt: NetworkContext, **kwargs) -> str: return ("\n").join([ codeSnippet.template.generate( - ExecutionBlock._mangleNodeRep(ctxt, { + ExecutionBlock._mangleOpRepr(ctxt, { **codeSnippet.operatorRepresentation, **kwargs })) for codeSnippet in self.codeSnippets @@ -2455,15 +2510,12 @@ def inputs(self) -> List[VariableBuffer]: """ inputs = [] - graphInputs = [tensor.name for tensor in self.graph.inputs] + for tensor in self.graph.inputs: + if self.ctxt.is_global(tensor.name): + buffer = self.ctxt.lookup(tensor.name) + if isinstance(buffer, self.ctxt.VariableBuffer) and len(buffer._users) > 0: + inputs.append(buffer) - for key, value in self.ctxt.globalObjects.items(): - if not isinstance(value, self.ctxt.VariableBuffer) or value._users == []: - continue - if key not in graphInputs: - continue - - inputs += [value] return inputs def outputs(self) -> List[VariableBuffer]: @@ -2477,16 +2529,12 @@ def outputs(self) -> List[VariableBuffer]: """ outputs = [] - graphOutputs = [tensor.name for tensor in self.graph.outputs] - - for key, value in self.ctxt.globalObjects.items(): - - if not isinstance(value, self.ctxt.VariableBuffer): - continue - if key not in graphOutputs: - continue + for tensor in self.graph.outputs: + if self.ctxt.is_global(tensor.name): + buffer = self.ctxt.lookup(tensor.name) + if isinstance(buffer, self.ctxt.VariableBuffer): + outputs.append(buffer) - outputs += [value] return outputs def codeTransform(self, verbose: CodeGenVerbosity = _NoVerbosity): diff --git a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py index d08978f5e0..dfadf558b4 100644 --- a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py +++ b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py @@ -62,8 +62,11 @@ def _initEngineColoringDeployer(self, engineMapperCls: Type[EngineMapper]): def lower(self, graph: gs.Graph) -> gs.Graph: graph = super().lower(graph) - uncoloredNodes = [node.name for node in graph.nodes if "engine" not in node.attrs] - assert len(uncoloredNodes) == 0, f"Missing engine color for nodes {uncoloredNodes}" + uncoloredNodes = [node for node in graph.nodes if "engine" not in node.attrs] + uncoloredOperations = set(node.op for node in uncoloredNodes) + assert len( + uncoloredNodes + ) == 0, f"Missing engine color for nodes {[node.name for node in uncoloredNodes]} with operations {uncoloredOperations}" return graph def _mapNode(self, node: gs.Node) -> Union[ONNXLayer, Any]: diff --git a/Deeploy/Targets/CortexM/Templates/CMSISUtils.py b/Deeploy/Targets/CortexM/Templates/CMSISUtils.py index d8f03597af..3d0cbbc311 100644 --- a/Deeploy/Targets/CortexM/Templates/CMSISUtils.py +++ b/Deeploy/Targets/CortexM/Templates/CMSISUtils.py @@ -90,8 +90,8 @@ def bindConvParams(ctxt, name, repName, batch, operatorRepresentation): operatorRepresentation[f'{repName}_conv_params'] = ctxt.lookup(f'{name}_conv_params').name convQuantDict = { - 'multiplier': ctxt._mangle(operatorRepresentation['mul']), - 'shift': ctxt._mangle(operatorRepresentation['shift']), + 'multiplier': operatorRepresentation['mul'], + 'shift': operatorRepresentation['shift'], } nameList += [ctxt.hoistStruct(convQuantDict, f'{name}_quant_params', cmsis_nn_per_channel_quant_params)] operatorRepresentation[f'{repName}_quant_params'] = ctxt.lookup(f'{name}_quant_params').name diff --git a/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py b/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py index fce7d0bdeb..abb508cb61 100644 --- a/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py +++ b/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py @@ -44,7 +44,7 @@ def alignToContext(self, ctxt: NetworkContext, operatorRepresentation['data_in_signed'] = data_in._signed operatorRepresentation['offset'] = (data_in._signed == 0) * int(data_in.nLevels / 2) - operatorRepresentation['output_name'] = ctxt._mangle(data_out.name) + operatorRepresentation['output_name'] = data_out.name return ctxt, operatorRepresentation, [] diff --git a/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py b/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py index 67d9b0f319..a8269d2eb2 100644 --- a/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py @@ -43,7 +43,7 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, size = operatorRepresentation['lastDimLength'] name = operatorRepresentation['nodeName'] + f"_buffer" ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer'] = ctxt._mangle(name) + operatorRepresentation['ctxtBuffer'] = name operatorRepresentation['ctxtBufferSize'] = size return ctxt, operatorRepresentation, [name] diff --git a/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py index f9d53f8d82..f9c94364d0 100644 --- a/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py @@ -28,13 +28,12 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import uint16_t from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ - _invertPermutation, _permuteList + _invertPermutation, _permuteHyperRectangle from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TileConstraint import TileConstraint from Deeploy.TilingExtension.TilerModel import TilerModel -from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, TilingSchedule, \ - VariableReplacementScheme +from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, TilingSchedule, VariableReplacementScheme class TransposeTileConstraint(TileConstraint): @@ -68,8 +67,6 @@ def serializeTilingSolution( inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) - inputInCubes = [] - replacementTypes = {} replacements: Dict[str, List[int]] = {} @@ -79,28 +76,16 @@ def serializeTilingSolution( replacementTypes[f"dimLen_{dim}"] = PointerClass(uint16_t) replacements[f"dimLen_{dim}"] = [] - perm = operatorRepresentation['perm'] - invPerm = _invertPermutation(perm) - - for cube in outputCubes: - - inCubeDims = _permuteList(cube.dims, invPerm) - - InCube = HyperRectangle(_permuteList(cube.offset, invPerm), inCubeDims) - inputInCubes.append(InCube) - - for dim in range(numDims): - replacements[f"dimLen_{dim}"].append(inCubeDims[dim]) - - inputLoadSchedule = [] - outputLoadSchedule = [] - - for a in inputInCubes: - inputLoadSchedule.append({"data_in": a}) - - for out in outputCubes: - outputLoadSchedule.append({"data_out": out}) + invPerm = _invertPermutation(operatorRepresentation['perm']) + inputCubes = [] + for outCube in outputCubes: + inCube = _permuteHyperRectangle(outCube, invPerm) + inputCubes.append(inCube) + for i, dim in enumerate(inCube.dims): + replacements[f"dimLen_{i}"].append(dim) + inputLoadSchedule = [{"data_in": cube} for cube in inputCubes] + outputLoadSchedule = [{"data_out": cube} for cube in outputCubes] tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) diff --git a/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py index 4cff06d064..e31914aa3b 100644 --- a/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py @@ -23,7 +23,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import copy from typing import Dict, List, Tuple import numpy as np @@ -34,7 +33,8 @@ from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TileConstraint import TileConstraint from Deeploy.TilingExtension.TilerModel import TilerModel -from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, TilingSchedule, VariableReplacementScheme +from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, TilingSchedule, \ + VariableReplacementScheme class iRMSNormTileConstraint(TileConstraint): @@ -75,7 +75,6 @@ def serializeTilingSolution( addrNames = ['data_in', 'weight', 'data_out'] inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) - replacements = {"size": []} replacementTypes = {"size": PointerClass(uint16_t)} @@ -87,9 +86,7 @@ def serializeTilingSolution( outputLoadSchedule = [] for cube in outputCubes: - - weightCube = copy.deepcopy(cube) - weightCube.dims = (cube.dims[-1],) + weightCube = HyperRectangle((cube.offset[-1],), (cube.dims[-1],)) inputLoadSchedule.append({"data_in": cube, "weight": weightCube}) for out in outputCubes: diff --git a/Deeploy/Targets/MemPool/Templates/GemmTemplate.py b/Deeploy/Targets/MemPool/Templates/GemmTemplate.py index d4852ba00f..6a92c7e7c6 100644 --- a/Deeploy/Targets/MemPool/Templates/GemmTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/GemmTemplate.py @@ -62,9 +62,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_A" operatorRepresentation['ctxtBuffer_A_size'] = size if isinstance(A, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_A'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_A'] = bufferName else: operatorRepresentation['ctxtBuffer_A'] = operatorRepresentation['A'] @@ -72,9 +72,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_B" operatorRepresentation['ctxtBuffer_B_size'] = size if isinstance(B, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_B'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_B'] = bufferName else: operatorRepresentation['ctxtBuffer_B'] = operatorRepresentation['B'] @@ -82,9 +82,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_C" operatorRepresentation['ctxtBuffer_C_size'] = size if isinstance(C, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_C'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_C'] = bufferName else: operatorRepresentation['ctxtBuffer_C'] = operatorRepresentation['C'] diff --git a/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py b/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py index 81d3cb1c95..acad82fe28 100644 --- a/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py @@ -44,7 +44,7 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, size = operatorRepresentation['lastDimLength'] * 192 name = operatorRepresentation['nodeName'] + f"_buffer" ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer'] = ctxt._mangle(name) + operatorRepresentation['ctxtBuffer'] = name operatorRepresentation['ctxtBufferSize'] = size return ctxt, operatorRepresentation, [name] diff --git a/Deeploy/Targets/MemPool/Templates/ITATemplate.py b/Deeploy/Targets/MemPool/Templates/ITATemplate.py index e5cf5ea76e..40f76c50cd 100644 --- a/Deeploy/Targets/MemPool/Templates/ITATemplate.py +++ b/Deeploy/Targets/MemPool/Templates/ITATemplate.py @@ -322,9 +322,8 @@ def alignToContext(self, ctxt: NetworkContext, if hasattr(data_out, "_signed") and hasattr(data_out, "nLevels"): operatorRepresentation['output_offset'] = -(data_out._signed == 0) * int(data_out.nLevels // 2) - operatorRepresentation['data_in_array'] = ctxt._mangle(operatorRepresentation['nodeName'] + f"_data_in_array") - operatorRepresentation['quant_params_array'] = ctxt._mangle(operatorRepresentation['nodeName'] + - f"_quant_params_array") + operatorRepresentation['data_in_array'] = f"{nodeName}_data_in_array" + operatorRepresentation['quant_params_array'] = f"{nodeName}_quant_params_array" return ctxt, operatorRepresentation, nameList diff --git a/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py b/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py index b336af20ba..7806a66485 100644 --- a/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py @@ -72,9 +72,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_A" operatorRepresentation['ctxtBuffer_A_size'] = size if isinstance(A, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_A'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_A'] = bufferName else: operatorRepresentation['ctxtBuffer_A'] = operatorRepresentation['A'] @@ -82,9 +82,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_B" operatorRepresentation['ctxtBuffer_B_size'] = size if isinstance(B, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_B'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_B'] = bufferName else: operatorRepresentation['ctxtBuffer_B'] = operatorRepresentation['B'] @@ -92,9 +92,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_C" operatorRepresentation['ctxtBuffer_C_size'] = size if isinstance(C, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_C'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_C'] = bufferName else: operatorRepresentation['ctxtBuffer_C'] = operatorRepresentation['C'] diff --git a/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py b/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py index d8165c6e51..db04b500e6 100644 --- a/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py @@ -77,9 +77,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_A" operatorRepresentation['ctxtBuffer_A_size'] = size if isinstance(A, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_A'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_A'] = bufferName else: operatorRepresentation['ctxtBuffer_A'] = operatorRepresentation['A'] @@ -87,9 +87,9 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, name = operatorRepresentation['nodeName'] + f"_buffer_B" operatorRepresentation['ctxtBuffer_B_size'] = size if isinstance(B, ConstantBuffer): - names += [name] - ctxt.hoistTransientBuffer(name, size) - operatorRepresentation['ctxtBuffer_B'] = ctxt._mangle(name) + bufferName = ctxt.hoistTransientBuffer(name, size) + names += [bufferName] + operatorRepresentation['ctxtBuffer_B'] = bufferName else: operatorRepresentation['ctxtBuffer_B'] = operatorRepresentation['B'] diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py index 8457c17e88..70eea8772a 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py @@ -35,7 +35,7 @@ from Deeploy.TilingExtension.TileConstraint import TileConstraint from Deeploy.TilingExtension.TilerModel import PerformanceHint, TilerModel from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, TilingSchedule, \ - VariableReplacementScheme, calculateRectangleOffset + VariableReplacementScheme, calculateFlatOffsetInBytes class NeurekaDenseConv2DTileConstraint(TileConstraint): @@ -488,7 +488,7 @@ def serializeTilingSolution( _, _, _, absoluteCOffset = absoluteCube.absoluteOffset weightShape = ctxt.lookup(varWeight).shape WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateRectangleOffset(WeightCube, ctxt.lookup(varWeight))) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) inputLoadSchedule = [] outputLoadSchedule = [] diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py index 6364afcdf7..0a0e7153ec 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py @@ -35,7 +35,7 @@ from Deeploy.TilingExtension.TileConstraint import TileConstraint from Deeploy.TilingExtension.TilerModel import PerformanceHint, TilerModel from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, TilingSchedule, \ - VariableReplacementScheme, calculateRectangleOffset + VariableReplacementScheme, calculateFlatOffsetInBytes class NeurekaDWConv2DTileConstraint(TileConstraint): @@ -486,7 +486,7 @@ def serializeTilingSolution( _, _, _, absoluteCOffset = absoluteCube.absoluteOffset weightShape = ctxt.lookup(varWeight).shape WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateRectangleOffset(WeightCube, ctxt.lookup(varWeight))) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) inputLoadSchedule = [] outputLoadSchedule = [] diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py index 303cc6a4e7..c9bdf6a12e 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py @@ -35,7 +35,7 @@ from Deeploy.TilingExtension.TileConstraint import TileConstraint from Deeploy.TilingExtension.TilerModel import PerformanceHint, TilerModel from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, TilingSchedule, \ - VariableReplacementScheme, calculateRectangleOffset + VariableReplacementScheme, calculateFlatOffsetInBytes class NeurekaPWConv2DTileConstraint(TileConstraint): @@ -535,7 +535,7 @@ def serializeTilingSolution( _, _, _, absoluteCOffset = absoluteCube.absoluteOffset weightShape = ctxt.lookup(varWeight).shape WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateRectangleOffset(WeightCube, ctxt.lookup(varWeight))) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) inputLoadSchedule = [] outputLoadSchedule = [] diff --git a/Deeploy/Targets/PULPOpen/Bindings.py b/Deeploy/Targets/PULPOpen/Bindings.py index 547a29af10..5e13acf411 100644 --- a/Deeploy/Targets/PULPOpen/Bindings.py +++ b/Deeploy/Targets/PULPOpen/Bindings.py @@ -48,6 +48,8 @@ from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3Tiling import PULPL3Tiling from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPProfileUntiled import PULPProfileUntiled from Deeploy.Targets.PULPOpen.DataTypes import PULPDMAFuture +from Deeploy.Targets.PULPOpen.DMA.L3Dma import l3DmaHack +from Deeploy.Targets.PULPOpen.DMA.MchanDma import MchanDma from Deeploy.Targets.PULPOpen.Templates import ConvTemplate, FloatAddTemplate, FloatConvTemplate, FloatGELUTemplate, \ FloatGemmTemplate, FloatLayernormTemplate, FloatMatMulTemplate, FloatMaxPoolTemplate, FloatMulTemplate, \ FloatReluTemplate, FloatSoftmaxTemplate, GEMMTemplate, MatrixVectorTemplate, MaxPool2DTemplate, MulTemplate, \ @@ -56,7 +58,8 @@ iRMSNormTemplate, iSoftmaxTemplate from Deeploy.Targets.PULPOpen.TypeCheckers import PULPConvChecker, PULPLinearChecker, PULPMaxPoolChecker, \ PULPRequantShiftChecker -from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement +from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ + TilingVariableReplacementUpdate _clusterEntryClosureCallTemplate = NodeTemplate(""" // ${closureName} CLOSURE CALL @@ -115,29 +118,31 @@ TilingCallClosure(writeback = False), PULPSynchCoresPass(), ForkClosure(writeback = False, generateStruct = True), - PULPClusterTiling("L1"), + TilingVariableReplacementUpdate("L1"), + PULPClusterTiling("L2", "L1", MchanDma()), ArgumentStructGeneration(), MemoryManagementGeneration("L1"), - MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), TilingVariableReplacement("L2"), - PULPL3Tiling("L2"), + MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), + PULPL3Tiling("L3", "L2", l3DmaHack), PULPProfileUntiled(), ArgumentStructGeneration(), L3MemoryAwareFunctionCallClosure(writeback = False), - MemoryManagementGeneration("L3.*"), MemoryManagementGeneration("L2"), + MemoryManagementGeneration("L3.*"), MemoryManagementGeneration(), ]) ClusterTransformer = CodeTransformation([ TilingVariableReplacement("L1"), TilingCallClosure(writeback = False, generateStruct = True), - PULPClusterTiling("L1"), + TilingVariableReplacementUpdate("L1"), + PULPClusterTiling("L2", "L1", MchanDma()), ArgumentStructGeneration(), MemoryManagementGeneration("L1"), - MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), TilingVariableReplacement("L2"), - PULPL3Tiling("L2"), + MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), + PULPL3Tiling("L3", "L2", l3DmaHack), PULPProfileUntiled(), ArgumentStructGeneration(), L3MemoryAwareFunctionCallClosure(writeback = False), diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py index 47d19cb850..42b090776f 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py @@ -27,32 +27,23 @@ from typing import Dict, List, Literal, Tuple from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ - _invertPermutation, _permuteList + _invertPermutation, _permute, _permuteHyperRectangle from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation from Deeploy.Targets.PULPOpen.DataTypes import PULPStructDataTypes -from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, minimizeRectangleDims +from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, minimizeRectangle -def _transposedDMAStrides(ctxt: NetworkContext, rectangle: HyperRectangle, direction: Literal["ToL1", "FromL1"], +def _transposedDMAStrides(ctxt: NetworkContext, rect: HyperRectangle, direction: Literal["ToL1", "FromL1"], perm: List[int], L1Name: str, L2Name: str) -> Tuple[HyperRectangle, List[int], List[int]]: _invPerm = _invertPermutation(perm) - rectangle = HyperRectangle(_permuteList(rectangle.offset, _invPerm), _permuteList(rectangle.dims, _invPerm)) + inRect = _permuteHyperRectangle(rect, _invPerm) - contiguousDims = [permIdx == rangeIdx for permIdx, rangeIdx in zip(perm, range(len(perm)))] - workList = [] - - for idx, dim in enumerate(contiguousDims): - if dim: - workList.append(rectangle.dims[idx]) - else: - workList.append(1) - - maxTransferRect = copy.copy(rectangle) - maxTransferRect.dims = tuple(workList) + maxTransferDims = tuple(inRect.dims[idx] if idx == permIdx else 1 for idx, permIdx in enumerate(perm)) + maxTransferRect = HyperRectangle(inRect.offset, maxTransferDims) referenceBuffer = copy.copy(ctxt.lookup(L2Name)) - referenceBuffer.shape = _permuteList(referenceBuffer.shape, _invPerm) - minRect, referenceRect = minimizeRectangleDims(maxTransferRect, referenceBuffer) + referenceBuffer.shape = _permute(referenceBuffer.shape, _invPerm) + minRect, referenceShape = minimizeRectangle(maxTransferRect, referenceBuffer.shape) droppedIdx = [ idx for idx in range(len(perm)) @@ -70,7 +61,7 @@ def _transposedDMAStrides(ctxt: NetworkContext, rectangle: HyperRectangle, direc newPerm.append(p - sub) strides = [1] - for dim in reversed(referenceRect.dims[1:]): + for dim in reversed(referenceShape[1:]): strides.insert(0, strides[0] * dim) permStrides = [strides[idx] for idx in newPerm] diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py index 3f15f04680..b81d043dd2 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py @@ -26,18 +26,38 @@ from typing import Tuple from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity +from Deeploy.TilingExtension.AsyncDma import AsyncDma +from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ + DoubleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ + SingleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ + ProfilingDoubleBufferingTilingMixIn, ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingMixIn -from .PULPClusterTilingDB import ProfilingPULPClusterTilingGenerationDB, PULPClusterTilingGenerationDB -from .PULPClusterTilingSB import ProfilingPULPClusterTilingGenerationSB, PULPClusterTilingGenerationSB + +class PULPClusterTilingGenerationSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): + pass + + +class ProfilingPULPClusterTilingGenerationSB(SingleBufferingTilingCodeGeneration, ProfilingSingleBufferingTilingMixIn): + pass + + +class PULPClusterTilingGenerationDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): + pass + + +class ProfilingPULPClusterTilingGenerationDB(DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn): + pass class PULPClusterTiling(CodeTransformationPass): - def __init__(self, targetMemLevel: str): - self.SB = PULPClusterTilingGenerationSB(targetMemLevel) - self.profilingSB = ProfilingPULPClusterTilingGenerationSB(targetMemLevel) - self.DB = PULPClusterTilingGenerationDB(targetMemLevel) - self.profilingDB = ProfilingPULPClusterTilingGenerationDB(targetMemLevel) + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): + self.SB = PULPClusterTilingGenerationSB(externalMemory, localMemory, dma) + self.profilingSB = ProfilingPULPClusterTilingGenerationSB(externalMemory, localMemory, dma) + self.DB = PULPClusterTilingGenerationDB(externalMemory, localMemory, dma) + self.profilingDB = ProfilingPULPClusterTilingGenerationDB(externalMemory, localMemory, dma) def apply(self, ctxt: NetworkContext, diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingDB.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingDB.py deleted file mode 100644 index e13c1bbad0..0000000000 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingDB.py +++ /dev/null @@ -1,359 +0,0 @@ -# ---------------------------------------------------------------------- -# -# File: PULPClusterTilingDB.py -# -# Last edited: 25.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -from typing import Dict, List, Tuple - -from Deeploy.DeeployTypes import CodeSnippet, ExecutionBlock, NetworkContext, NodeTemplate, OperatorRepresentation -from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterTilingSB import PULPClusterTilingSB, _DMAUpdate -from Deeploy.Targets.PULPOpen.DataTypes import PULPStructDataTypes -from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ - ProfilingDoubleBufferingTilingMixIn, TilingMetaInfo -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme - -_moveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -if (${tileNum} < ${numTiles}[*${tileIdxPtr}+1]){ -dory_dma_memcpy_mindims_async(&${stateReference}); -} - -""") - -_moveTileOutTemplate = NodeTemplate(""" - -// EXPORT TILE ${innerTilePtr} to ${outerTilePtr} -if((${tileNum}) % 2 == 0){ -dory_dma_memcpy_mindims_async(&${stateReference}); -} else { -dory_dma_memcpy_mindims_async(&${_stateReference}); -} -""") - -_blockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -if((${tileNum}) > 1){ -if((${tileNum}) % 2 == 0){ -dory_dma_barrier(&${stateReference}); -} else { -dory_dma_barrier(&${_stateReference}); -} -} - -""") - -_finalBlockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -dory_dma_barrier(&${stateReference}); -dory_dma_barrier(&${_stateReference}); -""") - -_updateDMATransferStructTemplate = NodeTemplate(""" - -// UPDATE DMA STRUCT ${stateReference}, ${_stateReference} -${stateReference}.ext = (((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]); -${stateReference}.mchan_cmd = ${mchanCmdPtr}[${tileNum}]; -${stateReference}.length_1d_copy = ${length1dPtr}[${tileNum}]; -${stateReference}.number_of_1d_copies = ${number1dPtr}[${tileNum}]; -${stateReference}.number_of_2d_copies = ${number2dPtr}[${tileNum}]; -${stateReference}.loc = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -${locPtr} = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}-1]); -""") - -_outUpdateDMATransferStructTemplate = NodeTemplate(""" - -if ((${tileNum}) % 2 == 0){ -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.ext = ((char*)${extPtr} + ${extOffsetPtr}[${tileNum}]); -${stateReference}.mchan_cmd = ${mchanCmdPtr}[${tileNum}]; -${stateReference}.length_1d_copy = ${length1dPtr}[${tileNum}]; -${stateReference}.number_of_1d_copies = ${number1dPtr}[${tileNum}]; -${stateReference}.number_of_2d_copies = ${number2dPtr}[${tileNum}]; -${stateReference}.loc = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -} else { -${_stateReference}.ext = ((char*)${extPtr} + ${extOffsetPtr}[${tileNum}]); -${_stateReference}.mchan_cmd = ${mchanCmdPtr}[${tileNum}]; -${_stateReference}.length_1d_copy = ${length1dPtr}[${tileNum}]; -${_stateReference}.number_of_1d_copies = ${number1dPtr}[${tileNum}]; -${_stateReference}.number_of_2d_copies = ${number2dPtr}[${tileNum}]; -${_stateReference}.loc = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -} -${locPtr} = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); - -""") - - -class PULPClusterTilingDB(PULPClusterTilingSB): - - _blockTileOutTemplate = _blockTileOutTemplate - _updateDMATransferStructTemplate = _updateDMATransferStructTemplate - _moveTileOutTemplate = _moveTileOutTemplate - _moveTileInTemplate = _moveTileInTemplate - - def _hoistDMAUpdates(self, ctxt: NetworkContext, tensorName: str, updateList: List[_DMAUpdate], - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict]: - nodeName = operatorRepresentation['nodeName'] - - operatorRepresentation = operatorRepresentation.copy() - - dmaName = self._DMAStructName(tensorName, nodeName) - # operatorRepresentation['stateReference'] = dmaName - # operatorRepresentation['tileNum'] = "TILING_I" - operatorRepresentation['locPtr'] = ctxt.lookup(operatorRepresentation[tensorName]).name - operatorRepresentation['baseLocPtr'] = ctxt.hoistReference(operatorRepresentation['locPtr'], - operatorRepresentation['locPtr'] + "_ref") - operatorRepresentation['_stateReference'] = self._DMAStructName(tensorName, nodeName) + "_1" - ctxt.lookup(operatorRepresentation['baseLocPtr'])._memoryLevel = self.targetMemLevel - - namePrefix = self.prefix + f"{nodeName}_{tensorName}" - - ctxt, operatorRepresentation = super()._hoistDMAUpdates(ctxt, tensorName, updateList, operatorRepresentation) - - locOffsetList = [] - locBaseOffset = updateList[0].locOffset - for update in updateList: - locOffsetList.append(int(update.locOffset) - locBaseOffset) - - name = namePrefix + "_locOffset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], locOffsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'locOffsetPtr') - - return ctxt, operatorRepresentation - - def _generateEgressPointerUpdates( - self, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, - nodeMemoryConstraint, tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(_outUpdateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateEgressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - egressDMATransferCalls = [] - egressDMAWaitStatements = [] - - exportLoadStep = tilingSchedule.outputLoadSchedule[0] - for key, rectangle in exportLoadStep.items(): - externalPtr = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - internalPtr = ctxt.lookup(operatorRepresentation[key]) - - tensorName = key - nodeName = operatorRepresentation['nodeName'] - dmaName = self._DMAStructName(tensorName, nodeName) - - finalMemoryLevel = TilingCodeGeneration.isFinalMemoryLevel(nodeMemoryConstraint, internalPtr) - struct = self._rectToDMAStruct(ctxt, rectangle, "FromL1", internalPtr.name, externalPtr.name, - finalMemoryLevel) - _ = ctxt.hoistStruct(struct, dmaName, PULPStructDataTypes.DMA_copy) - ctxt.lookup(dmaName)._users += [operatorRepresentation['nodeName']] - - tensorName = key + "_1" - nodeName = operatorRepresentation['nodeName'] - _dmaName = self._DMAStructName(tensorName, nodeName) - - struct = self._rectToDMAStruct(ctxt, rectangle, "FromL1", internalPtr.name, externalPtr.name, - finalMemoryLevel) - _ = ctxt.hoistStruct(struct, _dmaName, PULPStructDataTypes.DMA_copy) - ctxt.lookup(_dmaName)._users += [operatorRepresentation['nodeName']] - - egressDMATransferCalls.append( - CodeSnippet( - self._moveTileOutTemplate, { - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName, - "_stateReference": _dmaName - })) - - egressDMAWaitStatements.append( - CodeSnippet( - self._blockTileOutTemplate, { - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName, - "_stateReference": _dmaName - })) - - return egressDMATransferCalls, egressDMAWaitStatements - - def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, - nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, - variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - tileIdxPtr = self._hoistTileIdxPtr(ctxt, operatorRepresentation) - - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateIngressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - egressDMATransferCalls, egressDMAWaitStatements = self._generateEgressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - ctxt, ingressDMAUpdates = self._generateIngressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - ctxt, egressDMAUpdates = self._generateEgressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - - variableUpdates = self._generateVariableUpdates(tilingSchedule, variableReplacement, ctxt, - operatorRepresentation) - - for transaction in ingressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I+1" - _operatorRepresentation["numTiles"] = operatorRepresentation['numTiles'] - _operatorRepresentation["tileIdxPtr"] = tileIdxPtr - - for transaction in ingressDMAUpdates: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I+1" - - for transaction in egressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I" - - for transaction in egressDMAWaitStatements: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation['tileNum'] = "TILING_I" - - for transaction in egressDMAUpdates: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I" - - for transaction in variableUpdates: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I" - - openLoopStatement = [ - CodeSnippet(self._openTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - closeLoopStatement = [ - CodeSnippet(self._closeTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - setupStatements = [] - teardownStatements = [] - - teardownStatements += [ - CodeSnippet(self._releaseDMATemplate, - {"stateReference": ingressDMAUpdates[0].operatorRepresentation["stateReference"]}) - ] - - setupStatements += [CodeSnippet(self._initDMATemplate, {"channelName": "dma_channel"})] - setupStatements += [ - CodeSnippet(self._setDMAChannelTemplate, { - **transaction.operatorRepresentation, "channelName": "dma_channel" - }) for transaction in ingressDMAUpdates - ] - - for transaction in egressDMAUpdates: - _operatorRepresentation = transaction.operatorRepresentation.copy() - _operatorRepresentation["channelName"] = "dma_channel" - setupStatements.append(CodeSnippet(self._setDMAChannelTemplate, _operatorRepresentation.copy())) - _operatorRepresentation["channelName"] = "dma_channel" - _operatorRepresentation["stateReference"] = _operatorRepresentation["_stateReference"] - setupStatements.append(CodeSnippet(self._setDMAChannelTemplate, _operatorRepresentation.copy())) - - for transaction in ingressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation.copy() - _operatorRepresentation["tileNum"] = 0 - _operatorRepresentation["numTiles"] = operatorRepresentation['numTiles'] - _operatorRepresentation["tileIdxPtr"] = tileIdxPtr - setupStatements.append(CodeSnippet(transaction.template, _operatorRepresentation)) - - for transaction in egressDMAWaitStatements: - _operatorRepresentation = transaction.operatorRepresentation.copy() - _operatorRepresentation['tileNum'] = ctxt.lookup(operatorRepresentation["numTiles"]).values[-1] - teardownStatements.append(CodeSnippet(_finalBlockTileOutTemplate, _operatorRepresentation)) - - metaInfo = TilingMetaInfo(nodeName = operatorRepresentation['nodeName'] + "_L2", - nodeOps = operatorRepresentation['nodeOps'], - numTiles = len(tilingSchedule.outputLoadSchedule), - tileIdxVar = "TILING_I", - kernelLevelTiling = True) - - newExecutionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements[-1:], ingressDMAUpdates, - egressDMATransferCalls, egressDMAWaitStatements[-1:], - egressDMAUpdates, variableUpdates, openLoopStatement, - closeLoopStatement, setupStatements, teardownStatements) - - return ctxt, newExecutionBlock, True - - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == 2: - return ctxt, executionBlock, False - - allNumTiles = [len(schedule.outputLoadSchedule) for schedule in tilingSchedules] - operatorRepresentation["numTiles"] = self._hoistNumTiles(ctxt, operatorRepresentation['nodeName'], - tilingSchedules) - - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) - - -class PULPClusterTilingGenerationDB(PULPClusterTilingDB, DoubleBufferingTilingMixIn): - pass - - -class ProfilingPULPClusterTilingGenerationDB(PULPClusterTilingDB, ProfilingDoubleBufferingTilingMixIn): - pass diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingSB.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingSB.py deleted file mode 100644 index 90dc3b2b2b..0000000000 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTilingSB.py +++ /dev/null @@ -1,673 +0,0 @@ -# ---------------------------------------------------------------------- -# -# File: PULPClusterTiling.py -# -# Last edited: 17.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -from collections import namedtuple -from typing import Dict, List, Literal, Optional, Tuple, Type - -import numpy as np - -import Deeploy.CommonExtensions.DataTypes as BasicDataTypes -from Deeploy.AbstractDataTypes import Immediate, PointerClass -from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ - _invertPermutation, _permuteList -from Deeploy.DeeployTypes import CodeSnippet, ConstantBuffer, ExecutionBlock, NetworkContext, NodeTemplate, \ - OperatorRepresentation -from Deeploy.Targets.PULPOpen.CodeTransformationPasses import AutoTransposeUtils -from Deeploy.Targets.PULPOpen.DataTypes import PULPStructDataTypes -from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import ProfilingSingleBufferingTilingMixIn, \ - SingleBufferingTilingMixIn, TilingMetaInfo -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme, \ - calculateRectangleOffset, minimizeRectangleDims - -_openTileLoopTemplate = NodeTemplate(""" - -// TILING LOOP -for (int TILING_I=${numTiles}[*${tileIdxPtr}]; TILING_I<${numTiles}[(*${tileIdxPtr})+1]; TILING_I++){ -""") - -_closeTileLoopTemplate = NodeTemplate(""" - -// CLOSE TILING LOOP -} -*${tileIdxPtr} += 1; - -""") - -_moveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -dory_dma_memcpy_mindims_async(&${stateReference}); - -""") - -_iteratedMoveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -// ITERATED - -<% -_extStrides = [stride * stateStruct.value['length_1d_copy'].value for stride in remainderStrides] -_locStride = f"{stateReference}.length_1d_copy * {stateReference}.number_of_1d_copies * {stateReference}.number_of_2d_copies" - -stateStruct.value['ext'] = str(stateReference) + ".ext" -stateStruct.value['loc'] = str(stateReference) + ".loc" -stateStruct.value['tid'] = str(stateReference) + ".tid" -stateStruct.value['stride_2d'] = str(stateReference) + ".stride_2d" -stateStruct.value['stride_1d'] = str(stateReference) + ".stride_1d" -stateStruct.value['number_of_2d_copies'] = str(stateReference) + ".number_of_2d_copies" -stateStruct.value['number_of_1d_copies'] = str(stateReference) + ".number_of_1d_copies" -stateStruct.value['length_1d_copy'] = str(stateReference) + ".length_1d_copy" -%> - -int8_t * bu_${stateReference}_loc = ${stateReference}.loc; -int8_t * bu_${stateReference}_ext = ${stateReference}.ext; - -% for idx, dimLen in enumerate(dimLens): -uint16_t ${nodeName}_${tensorName}_dimLen_${idx} = ${dimLen}[${tileNum}]; -for(int i_${idx} = 0; i_${idx} < ${nodeName}_${tensorName}_dimLen_${idx}; i_${idx}++){ -%endfor -${stateStruct.typeName} trans_${stateReference} = (${stateStruct.typeName}) ${str(stateStruct)}; -dory_dma_memcpy_mindims_async(&trans_${stateReference}); -${stateStruct.value['loc']} = (((int8_t*) ${stateStruct.value['loc']}) + ${_locStride}); -% for idx, _ in enumerate(dimLens): -${stateStruct.value['ext']} = (((int8_t*) ${stateStruct.value['ext']}) + (${_extStrides[idx]})); -} -${stateStruct.value['ext']} = (((int8_t*) ${stateStruct.value['ext']}) - ${nodeName}_${tensorName}_dimLen_${len(dimLens) -1 - idx} * ${_extStrides[idx]}); -%endfor - -${stateStruct.value['loc']} = bu_${stateReference}_loc; -${stateStruct.value['ext']} = bu_${stateReference}_ext; - -""") - -_blockTileInTemplate = NodeTemplate(""" - -// BLOCKING IMPORT TILE ${innerTilePtr} -dory_dma_barrier(&${stateReference}); - -""") - -_moveTileOutTemplate = NodeTemplate(""" - -// EXPORT TILE ${innerTilePtr} to ${outerTilePtr} -dory_dma_memcpy_mindims_async(&${stateReference}); - -""") - -_blockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -dory_dma_barrier(&${stateReference}); - -""") - -_updateDMATransferStructTemplate = NodeTemplate(""" - -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.ext = ((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]; -${stateReference}.length_1d_copy = ${length1dPtr}[${tileNum}]; -${stateReference}.number_of_1d_copies = ${number1dPtr}[${tileNum}]; -${stateReference}.number_of_2d_copies = ${number2dPtr}[${tileNum}]; - -${stateReference}.stride_1d = ${stride1dPtr}[${tileNum}]; -${stateReference}.stride_2d = ${stride2dPtr}[${tileNum}]; - -${stateReference}.mchan_cmd = ${mchanCmdPtr}[${tileNum}]; -""") - -_updateReferenceTemplate = NodeTemplate(""" - -// UPDATE VARIABLE ${reference} -*${reference} = ${baseReference}[${tileNum}]; -""") - -_initDMATemplate = NodeTemplate(""" -int32_t ${channelName} = dory_dma_allocate(); -""") - -_setDMAChannelTemplate = NodeTemplate(""" -${stateReference}.tid = ${channelName}; -""") - -_releaseDMATemplate = NodeTemplate(""" -dory_dma_free(&${stateReference}); -""") - -# ADD NUM TRANSFERS VARIABLE - -_DMAUpdate = namedtuple( - "_DMAUpdate", - "extOffset locOffset length_1d_copy number_of_1d_copies number_of_2d_copies stride_1d stride_2d mchan_cmd") - - -class PULPClusterTilingSB(TilingCodeGeneration): - - _prefix = "TILING_REPLACED_" - - _openTileLoopTemplate = _openTileLoopTemplate - _closeTileLoopTemplate = _closeTileLoopTemplate - - _moveTileInTemplate = _moveTileInTemplate - _iteratedMoveTileInTemplate = _iteratedMoveTileInTemplate - _blockTileInTemplate = _blockTileInTemplate - - _moveTileOutTemplate = _moveTileOutTemplate - _blockTileOutTemplate = _blockTileOutTemplate - - _updateDMATransferStructTemplate = _updateDMATransferStructTemplate - _updateReferenceTemplate = _updateReferenceTemplate - - _initDMATemplate = _initDMATemplate - _setDMAChannelTemplate = _setDMAChannelTemplate - _releaseDMATemplate = _releaseDMATemplate - - @property - def prefix(self): - return self._prefix + self.targetMemLevel + "_" - - def _DMAStructName(self, tensorName: str, nodeName: str) -> str: - return f"{self.prefix}_DMA_{nodeName}_{tensorName}" - - @classmethod - def _generatePointerUpdates(cls, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - loadSchedule: List[Dict[str, - HyperRectangle]], nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedule: TilingSchedule) -> Dict[str, _DMAUpdate]: - updateDict = {} - deltaOffsets = {} - - for idx, loadStep in enumerate(loadSchedule): - for stepIdx, (key, rect) in enumerate(loadStep.items()): - - if key in tilingSchedule.outputBaseOffsets.keys(): - baseOffsets = tilingSchedule.outputBaseOffsets[key] - direction = "FromL1" - else: - baseOffsets = tilingSchedule.inputBaseOffsets[key] - direction = "ToL1" - - if key not in updateDict.keys(): - updateDict[key] = [] - if key not in deltaOffsets.keys(): - deltaOffsets[key] = 0 - - referenceBuffer = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - l1Buffer = ctxt.lookup(operatorRepresentation[key]) - - finalMemoryLevel = TilingCodeGeneration.isFinalMemoryLevel(nodeMemoryConstraint, l1Buffer) - - if (f"in{stepIdx}_perm" in operatorRepresentation - and key in tilingSchedule.inputBaseOffsets.keys()) and (finalMemoryLevel == False): - perm = operatorRepresentation[f"in{stepIdx}_perm"] - struct, _, _ = AutoTransposeUtils.generateTransposedDMAStruct(ctxt, rect, direction, perm, - l1Buffer.name, - l1Buffer._referenceName) - - _invPerm = _invertPermutation(perm) - _rect = copy.copy(rect) - _referenceBuffer = copy.copy(referenceBuffer) - _rect.offset = _permuteList(rect.offset, _invPerm) - _rect.dims = _permuteList(rect.dims, _invPerm) - _referenceBuffer.shape = _permuteList(referenceBuffer.shape, _invPerm) - - accOffset = calculateRectangleOffset(_rect, _referenceBuffer) - - else: - struct = cls._rectToDMAStruct(ctxt, rect, direction, l1Buffer.name, l1Buffer._referenceName, - finalMemoryLevel) - accOffset = calculateRectangleOffset(rect, referenceBuffer) - - length_1d_copy = struct.value['length_1d_copy'].value - number_of_1d_copies = struct.value['number_of_1d_copies'].value - number_of_2d_copies = struct.value['number_of_2d_copies'].value - stride_1d = struct.value['stride_1d'].value - stride_2d = struct.value['stride_2d'].value - mchan_cmd = struct.value['mchan_cmd'].value - - lIdx = idx % len(baseOffsets) - - sol = _DMAUpdate(accOffset, baseOffsets[lIdx], length_1d_copy, number_of_1d_copies, number_of_2d_copies, - stride_1d, stride_2d, mchan_cmd) - - deltaOffsets[key] = accOffset - updateDict[key].append(sol) - - return updateDict - - @classmethod - def _rectToDMAStruct(cls, ctxt: NetworkContext, rectangle: HyperRectangle, direction: Literal["ToL1", "FromL1"], - L1Name: str, L2Name: str, finalMemoryLevel: bool) -> PULPStructDataTypes.DMA_copy: - - referenceBuffer = ctxt.lookup(L2Name) - - rect, referenceRect = minimizeRectangleDims(rectangle, referenceBuffer) - assert len(rect.dims) <= 3, "PULP: Only 2D transfers are supported!" - - if direction == "ToL1": - _dir = 1 - else: - _dir = 0 - - length_1d_copy = rect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - - number_of_1d_copies = 1 - stride_1d = 0 - - if len(rect.dims) > 1: - number_of_1d_copies = rect.dims[-2] - stride_1d = referenceRect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - - if not finalMemoryLevel: - stride_1d = length_1d_copy - - number_of_2d_copies = 1 - stride_2d = 0 - - if len(rect.dims) > 2: - number_of_2d_copies = rect.dims[-3] - stride_2d = referenceRect.dims[-2] * stride_1d - - length_2d_copy = number_of_1d_copies * length_1d_copy - mchan_flags = _dir + 0x2 + 0x8 - if number_of_1d_copies > 1 or number_of_2d_copies > 1: - mchan_flags += 0x4 - mchan_cmd = length_2d_copy + (mchan_flags << 17) - - assert length_2d_copy <= 2**17, f"The DMA transfer size for mchan should be representable with 17 bits, current number of bits required is {np.ceil(np.log2(length_2d_copy))}" - - struct = PULPStructDataTypes.DMA_copy( - { - "ext": referenceBuffer.name, - "loc": L1Name, - "hwc_to_chw": 0, - "stride_2d": stride_2d, - "number_of_2d_copies": number_of_2d_copies, - "stride_1d": stride_1d, - "number_of_1d_copies": number_of_1d_copies, - "length_1d_copy": length_1d_copy, - "mchan_cmd": mchan_cmd, - "dir": _dir, - "tid": 0 - }, ctxt) - - return struct - - def _hoistConstantAndReference(self, - ctxt: NetworkContext, - constBuf: ConstantBuffer, - operatorRepresentation: OperatorRepresentation, - nodeName: str, - operatorRepresentationName: str, - immediateType: Optional[Type[Immediate]] = None) -> Tuple[NetworkContext, Dict]: - - if immediateType is None: - _type = PointerClass(BasicDataTypes.int32_t) - else: - _type = PointerClass(immediateType) - - name = constBuf.name - - ctxt.add(constBuf, "global") - constBuf._type = _type - constBuf._instance = constBuf._type(name, ctxt) - constBuf._users = [nodeName] - constBuf._memoryLevel = self.targetMemLevel - - refName = name + "_ref" - reference = ctxt.hoistReference(name, refName) - ctxt.lookup(reference)._memoryLevel = self.targetMemLevel - - operatorRepresentation[operatorRepresentationName] = refName - - return ctxt, operatorRepresentation - - def _hoistDMAUpdates(self, ctxt: NetworkContext, tensorName: str, updateList: List[_DMAUpdate], - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict]: - - operatorRepresentation = operatorRepresentation.copy() - - nodeName = operatorRepresentation['nodeName'] - - offsetList = [] - mchanCmdList = [] - len1dList = [] - num1dList = [] - num2dList = [] - stride1dList = [] - stride2dList = [] - for update in updateList: - offsetList.append(int(update.extOffset)) - mchanCmdList.append(int(update.mchan_cmd)) - len1dList.append(int(update.length_1d_copy)) - num1dList.append(int(update.number_of_1d_copies)) - num2dList.append(int(update.number_of_2d_copies)) - stride1dList.append(int(update.stride_1d)) - stride2dList.append(int(update.stride_2d)) - - dmaName = self._DMAStructName(tensorName, nodeName) - operatorRepresentation['stateReference'] = dmaName - operatorRepresentation['tileNum'] = "TILING_I" - operatorRepresentation['extPtr'] = ctxt.lookup(operatorRepresentation[tensorName])._referenceName - - namePrefix = self.prefix + f"{nodeName}_{tensorName}" - - name = namePrefix + "_offset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], offsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'extOffsetPtr') - - name = namePrefix + "_mchan_cmd" - cb = ctxt.ConstantBuffer(name, [len(updateList)], mchanCmdList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'mchanCmdPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['mchan_cmd']) - - name = namePrefix + "_length_1d_copy" - cb = ctxt.ConstantBuffer(name, [len(updateList)], len1dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'length1dPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['length_1d_copy']) - - name = namePrefix + "_number_of_1d_copies" - cb = ctxt.ConstantBuffer(name, [len(updateList)], num1dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'number1dPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['number_of_1d_copies']) - - name = namePrefix + "_number_of_2d_copies" - cb = ctxt.ConstantBuffer(name, [len(updateList)], num2dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'number2dPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['number_of_2d_copies']) - - name = namePrefix + "_stride_1d" - cb = ctxt.ConstantBuffer(name, [len(updateList)], stride1dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'stride1dPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['stride_1d']) - - name = namePrefix + "_stride_2d" - cb = ctxt.ConstantBuffer(name, [len(updateList)], stride2dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'stride2dPtr', - PULPStructDataTypes.DMA_copy.structTypeDict['stride_2d']) - - return ctxt, operatorRepresentation - - def _generateEgressPointerUpdates( - self, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, - nodeMemoryConstraint, tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateIngressPointerUpdates( - self, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.inputLoadSchedule, - nodeMemoryConstraint, tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateVariableUpdates(self, tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, - ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> List[CodeSnippet]: - - updates = [] - - for key in variableReplacement.perTileReplacements.keys(): - - buf = ctxt.lookup(operatorRepresentation[key]) - reference = str(buf._instance) - - updates.append( - CodeSnippet(self._updateReferenceTemplate, { - "reference": reference, - "tileNum": "TILING_I", - "baseReference": buf._referenceName - })) - - return updates - - def _generateDMACode(self, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation, loadSchedule: List[Dict[str, HyperRectangle]], - direction: Literal["ToL1", "FromL1"]) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - DMATransferCalls = [] - DMAWaitStatements = [] - - allNumTransfers = AutoTransposeUtils.allNumTransfers(ctxt, operatorRepresentation, loadSchedule, direction) - - transferNodeRep = {} - - if allNumTransfers != []: - - dimLens = [] - - for dim in range(len(allNumTransfers[0])): - dimVec = [transfer[dim] for transfer in allNumTransfers] - namePrefix = operatorRepresentation["nodeName"] + "_" - vecName = f"dimLen_{dim}" - - cb = ctxt.ConstantBuffer(namePrefix + vecName, [len(dimVec)], dimVec) - ctxt, transferNodeRep = self._hoistConstantAndReference(ctxt, cb, transferNodeRep, - operatorRepresentation['nodeName'], vecName) - - dimLens.append(str(cb._instance)) - - transferNodeRep['nodeName'] = operatorRepresentation['nodeName'] - transferNodeRep['dimLens'] = dimLens - transferNodeRep['tileNum'] = "TILING_I" - - loadStep = loadSchedule[0] - - for idx, (key, rectangle) in enumerate(loadStep.items()): - - permName = f"in{idx}_perm" - - externalPtr = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - internalPtr = ctxt.lookup(operatorRepresentation[key]) - - tensorName = key - nodeName = operatorRepresentation['nodeName'] - dmaName = self._DMAStructName(tensorName, nodeName) - - transferNodeRep = { - **transferNodeRep, - **{ - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName - } - } - - if permName in operatorRepresentation and direction == "ToL1": - perm = operatorRepresentation[permName] - struct, remainderStrides, numTransfers = AutoTransposeUtils.generateTransposedDMAStruct( - ctxt, rectangle, direction, perm, internalPtr.name, externalPtr.name) - locStride = np.prod( - rectangle.dims) // np.prod(numTransfers) * (externalPtr._type.referencedType.typeWidth // 8) - - transferNodeRep['tensorName'] = operatorRepresentation[key] - - transferNodeRep = {**transferNodeRep, **{"remainderStrides": remainderStrides, "locStride": locStride}} - - else: - finalMemoryLevel = TilingCodeGeneration.isFinalMemoryLevel(nodeMemoryConstraint, internalPtr) - - struct = self._rectToDMAStruct(ctxt, rectangle, direction, internalPtr.name, externalPtr.name, - finalMemoryLevel) - - transferNodeRep["stateStruct"] = struct - _ = ctxt.hoistStruct(struct, dmaName, PULPStructDataTypes.DMA_copy) - ctxt.lookup(dmaName)._users += [operatorRepresentation['nodeName']] - - if permName in operatorRepresentation and direction == "ToL1": - - DMATransferCalls.append(CodeSnippet(self._iteratedMoveTileInTemplate, transferNodeRep)) - else: - DMATransferCalls.append(CodeSnippet(self._moveTileInTemplate, transferNodeRep)) - - DMAWaitStatements.append(CodeSnippet(self._blockTileInTemplate, transferNodeRep)) - - return DMATransferCalls, DMAWaitStatements - - def _generateIngressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - importLoadStep = tilingSchedule.inputLoadSchedule - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateDMACode(nodeMemoryConstraint, ctxt, - operatorRepresentation, - importLoadStep, "ToL1") - return ingressDMATransferCalls, ingressDMAWaitStatements - - def _generateEgressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - exportLoadStep = tilingSchedule.outputLoadSchedule - egressDMATransferCalls, egressDMAWaitStatements = self._generateDMACode(nodeMemoryConstraint, ctxt, - operatorRepresentation, exportLoadStep, - "FromL1") - - return egressDMATransferCalls, egressDMAWaitStatements - - def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, - nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, - variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - tileIdxPtr = self._hoistTileIdxPtr(ctxt, operatorRepresentation) - - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateIngressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - egressDMATransferCalls, egressDMAWaitStatements = self._generateEgressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - ctxt, ingressDMAUpdates = self._generateIngressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - ctxt, egressDMAUpdates = self._generateEgressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - - openLoopStatement = [ - CodeSnippet(self._openTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - closeLoopStatement = [ - CodeSnippet(self._closeTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - setupStatements = [CodeSnippet(self._initDMATemplate, {"channelName": "dma_channel"})] - setupStatements += [ - CodeSnippet(self._setDMAChannelTemplate, { - **transaction.operatorRepresentation, "channelName": "dma_channel" - }) for transaction in ingressDMAUpdates + egressDMAUpdates - ] - - teardownStatements = [ - CodeSnippet(self._releaseDMATemplate, - {"stateReference": ingressDMAUpdates[0].operatorRepresentation["stateReference"]}) - ] - - variableUpdates = self._generateVariableUpdates(tilingSchedule, variableReplacement, ctxt, - operatorRepresentation) - - metaInfo = TilingMetaInfo(nodeName = operatorRepresentation['nodeName'] + "_L2", - nodeOps = operatorRepresentation['nodeOps'], - numTiles = len(tilingSchedule.outputLoadSchedule), - tileIdxVar = "TILING_I", - kernelLevelTiling = True) - - newExecutionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements, ingressDMAUpdates, - egressDMATransferCalls, egressDMAWaitStatements, - egressDMAUpdates, variableUpdates, openLoopStatement, - closeLoopStatement, setupStatements, teardownStatements) - - return ctxt, newExecutionBlock, True - - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - # SCHEREMO: hoist numTiles - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == 1: - return ctxt, executionBlock, False - - operatorRepresentation["numTiles"] = self._hoistNumTiles(ctxt, operatorRepresentation['nodeName'], - tilingSchedules) - - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) - - -class PULPClusterTilingGenerationSB(PULPClusterTilingSB, SingleBufferingTilingMixIn): - pass - - -class ProfilingPULPClusterTilingGenerationSB(PULPClusterTilingSB, ProfilingSingleBufferingTilingMixIn): - pass diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py index af744f8672..32854b3e93 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py @@ -26,18 +26,38 @@ from typing import Tuple from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity +from Deeploy.TilingExtension.AsyncDma import AsyncDma +from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ + DoubleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ + SingleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ + ProfilingDoubleBufferingTilingMixIn, ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingMixIn -from .PULPL3TilingDB import ProfilingPULPL3TilingGenerationDB, PULPL3TilingGenerationDB -from .PULPL3TilingSB import ProfilingPULPL3TilingGenerationSB, PULPL3TilingGenerationSB + +class PULPL3TilingGenerationSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): + pass + + +class ProfilingPULPL3TilingGenerationSB(SingleBufferingTilingCodeGeneration, ProfilingSingleBufferingTilingMixIn): + pass + + +class PULPL3TilingGenerationDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): + pass + + +class ProfilingPULPL3TilingGenerationDB(DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn): + pass class PULPL3Tiling(CodeTransformationPass): - def __init__(self, targetMemLevel: str): - self.SB = PULPL3TilingGenerationSB(targetMemLevel) - self.profilingSB = ProfilingPULPL3TilingGenerationSB(targetMemLevel) - self.DB = PULPL3TilingGenerationDB(targetMemLevel) - self.profilingDB = ProfilingPULPL3TilingGenerationDB(targetMemLevel) + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): + self.SB = PULPL3TilingGenerationSB(externalMemory, localMemory, dma) + self.DB = PULPL3TilingGenerationDB(externalMemory, localMemory, dma) + self.profilingSB = ProfilingPULPL3TilingGenerationSB(externalMemory, localMemory, dma) + self.profilingDB = ProfilingPULPL3TilingGenerationDB(externalMemory, localMemory, dma) def apply(self, ctxt: NetworkContext, diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingDB.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingDB.py deleted file mode 100644 index 6a3f80bd28..0000000000 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingDB.py +++ /dev/null @@ -1,329 +0,0 @@ -# ---------------------------------------------------------------------- -# -# File: PULPClusterTiling.py -# -# Last edited: 17.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -from typing import Dict, List, Tuple - -from Deeploy.DeeployTypes import CodeSnippet, ExecutionBlock, NetworkContext, NodeTemplate, OperatorRepresentation -from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3TilingSB import PULPL3TilingSB, _DMAUpdate -from Deeploy.Targets.PULPOpen.DataTypes import PULPStructDataTypes -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ - ProfilingDoubleBufferingTilingMixIn, TilingMetaInfo -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme - -_moveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -if (${tileNum} < ${numTiles}[*${tileIdxPtr}+1]){ -pi_cl_ram_copy_2d(get_ram_ptr(), ${stateReference}.pi_ram_addr, ${stateReference}.addr, ${stateReference}.size, ${stateReference}.stride, ${stateReference}.length, ${stateReference}.ext2loc, &${stateReference}); -} - -""") - -_moveTileOutTemplate = NodeTemplate(""" - -// EXPORT TILE ${innerTilePtr} to ${outerTilePtr} -if((${tileNum}) % 2 == 0){ -pi_cl_ram_copy_2d(get_ram_ptr(), ${stateReference}.pi_ram_addr, ${stateReference}.addr, ${stateReference}.size, ${stateReference}.stride, ${stateReference}.length, ${stateReference}.ext2loc, &${stateReference}); -} else { -pi_cl_ram_copy_2d(get_ram_ptr(), ${_stateReference}.pi_ram_addr, ${_stateReference}.addr, ${_stateReference}.size, ${_stateReference}.stride, ${_stateReference}.length, ${_stateReference}.ext2loc, &${_stateReference}); -} - -""") - -_blockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -if((${tileNum}) > 1){ -if((${tileNum}) % 2 == 0){ -pi_cl_ram_copy_wait(&${stateReference}); -} else { -pi_cl_ram_copy_wait(&${_stateReference}); -} -} - -""") - -_finalBlockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -pi_cl_ram_copy_wait(&${stateReference}); -% if numTiles > 1: -pi_cl_ram_copy_wait(&${_stateReference}); -% endif -""") - -_updateDMATransferStructTemplate = NodeTemplate(""" - -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.pi_ram_addr = ((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]; -${stateReference}.size = ${length1dPtr}[${tileNum}]; -${stateReference}.length = ${number1dPtr}[${tileNum}]; -${stateReference}.addr = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -${locPtr} = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}-1]); - -""") - -_outUpdateDMATransferStructTemplate = NodeTemplate(""" - -if ((${tileNum}) % 2 == 0){ -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.pi_ram_addr = ((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]; -${stateReference}.size = ${length1dPtr}[${tileNum}]; -${stateReference}.length = ${number1dPtr}[${tileNum}]; -${stateReference}.addr = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -} else { -${_stateReference}.pi_ram_addr = ((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]; -${_stateReference}.size = ${length1dPtr}[${tileNum}]; -${_stateReference}.length = ${number1dPtr}[${tileNum}]; -${_stateReference}.addr = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); -} -${locPtr} = (((char*)${baseLocPtr}) + ${locOffsetPtr}[${tileNum}]); - -""") - - -class PULPL3TilingDB(PULPL3TilingSB): - - _prefix = "TILING_REPLACED_" - _blockTileOutTemplate = _blockTileOutTemplate - _updateDMATransferStructTemplate = _updateDMATransferStructTemplate - _moveTileOutTemplate = _moveTileOutTemplate - _moveTileInTemplate = _moveTileInTemplate - - def _hoistDMAUpdates(self, ctxt: NetworkContext, tensorName: str, updateList: List[_DMAUpdate], - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict]: - - nodeName = operatorRepresentation['nodeName'] - - operatorRepresentation = operatorRepresentation.copy() - - dmaName = self._DMAStructName(tensorName, nodeName) - # operatorRepresentation['stateReference'] = dmaName - # operatorRepresentation['tileNum'] = "TILING_I" - operatorRepresentation['locPtr'] = ctxt.lookup(operatorRepresentation[tensorName]).name - operatorRepresentation['baseLocPtr'] = ctxt.hoistReference(operatorRepresentation['locPtr'], - operatorRepresentation['locPtr'] + "_ref") - operatorRepresentation['_stateReference'] = self._DMAStructName(tensorName, nodeName) + "_1" - ctxt.lookup(operatorRepresentation['baseLocPtr'])._memoryLevel = self.targetMemLevel - - namePrefix = self.prefix + f"{nodeName}_{tensorName}" - - ctxt, operatorRepresentation = super()._hoistDMAUpdates(ctxt, tensorName, updateList, operatorRepresentation) - - locOffsetList = [] - locBaseOffset = updateList[0].locOffset - for update in updateList: - locOffsetList.append(int(update.locOffset) - locBaseOffset) - - name = namePrefix + "_locOffset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], locOffsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'locOffsetPtr') - - return ctxt, operatorRepresentation - - def _generateEgressPointerUpdates( - self, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, - tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(_outUpdateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateEgressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - egressDMATransferCalls = [] - egressDMAWaitStatements = [] - exportLoadStep = tilingSchedule.outputLoadSchedule[0] - - for key, rectangle in exportLoadStep.items(): - externalPtr = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - internalPtr = ctxt.lookup(operatorRepresentation[key]) - - tensorName = key - nodeName = operatorRepresentation['nodeName'] - dmaName = self._DMAStructName(tensorName, nodeName) - - struct = self._rectToDMAStruct(ctxt, rectangle, "FromL2", internalPtr.name, externalPtr.name) - _ = ctxt.hoistStruct(struct, dmaName, PULPStructDataTypes.pi_cl_ram_req_t) - ctxt.lookup(dmaName)._users += [operatorRepresentation['nodeName']] - - tensorName = key + "_1" - nodeName = operatorRepresentation['nodeName'] - _dmaName = self._DMAStructName(tensorName, nodeName) - - struct = self._rectToDMAStruct(ctxt, rectangle, "FromL2", internalPtr.name, externalPtr.name) - _ = ctxt.hoistStruct(struct, _dmaName, PULPStructDataTypes.pi_cl_ram_req_t) - ctxt.lookup(_dmaName)._users += [operatorRepresentation['nodeName']] - - egressDMATransferCalls.append( - CodeSnippet( - self._moveTileOutTemplate, { - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName, - "_stateReference": _dmaName - })) - - egressDMAWaitStatements.append( - CodeSnippet( - self._blockTileOutTemplate, { - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName, - "_stateReference": _dmaName - })) - - return egressDMATransferCalls, egressDMAWaitStatements - - def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, - nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, - variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - tileIdxPtr = self._hoistTileIdxPtr(ctxt, operatorRepresentation) - - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateIngressDMACode( - tilingSchedule, ctxt, operatorRepresentation) - - egressDMATransferCalls, egressDMAWaitStatements = self._generateEgressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - ctxt, ingressDMAUpdates = self._generateIngressPointerUpdates(tilingSchedule, ctxt, operatorRepresentation) - ctxt, egressDMAUpdates = self._generateEgressPointerUpdates(tilingSchedule, ctxt, operatorRepresentation) - - variableUpdates = [] - - for transaction in ingressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I+1" - _operatorRepresentation["numTiles"] = operatorRepresentation['numTiles'] - _operatorRepresentation["tileIdxPtr"] = tileIdxPtr - - for transaction in ingressDMAUpdates: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I+1" - - for transaction in egressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I" - - for transaction in egressDMAWaitStatements: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation['tileNum'] = "TILING_I" - - for transaction in egressDMAUpdates: - _operatorRepresentation = transaction.operatorRepresentation - _operatorRepresentation["tileNum"] = "TILING_I" - - openLoopStatement = [ - CodeSnippet(self._openTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - closeLoopStatement = [ - CodeSnippet(self._closeTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - setupStatements = [] - teardownStatements = [] - - for transaction in ingressDMATransferCalls: - _operatorRepresentation = transaction.operatorRepresentation.copy() - _operatorRepresentation["tileNum"] = 0 - _operatorRepresentation["numTiles"] = operatorRepresentation['numTiles'] - _operatorRepresentation["tileIdxPtr"] = tileIdxPtr - setupStatements.append(CodeSnippet(transaction.template, _operatorRepresentation)) - - for transaction in egressDMAWaitStatements: - _operatorRepresentation = transaction.operatorRepresentation.copy() - _operatorRepresentation['tileNum'] = ctxt.lookup(operatorRepresentation["numTiles"]).values[-1] - _operatorRepresentation['numTiles'] = len(tilingSchedule.outputLoadSchedule) - teardownStatements.append(CodeSnippet(_finalBlockTileOutTemplate, _operatorRepresentation)) - - metaInfo = TilingMetaInfo(nodeName = operatorRepresentation['nodeName'] + "_L3", - nodeOps = operatorRepresentation['nodeOps'], - numTiles = len(tilingSchedule.outputLoadSchedule), - tileIdxVar = "TILING_I", - kernelLevelTiling = False) - - newExecutionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements, ingressDMAUpdates, - egressDMATransferCalls, egressDMAWaitStatements, - egressDMAUpdates, variableUpdates, openLoopStatement, - closeLoopStatement, setupStatements, teardownStatements) - - return ctxt, newExecutionBlock, True - - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == 2: - return ctxt, executionBlock, False - - allNumTiles = [len(schedule.outputLoadSchedule) for schedule in tilingSchedules] - operatorRepresentation["numTiles"] = self._hoistNumTiles(ctxt, operatorRepresentation['nodeName'], - tilingSchedules) - - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) - - -class PULPL3TilingGenerationDB(PULPL3TilingDB, DoubleBufferingTilingMixIn): - pass - - -class ProfilingPULPL3TilingGenerationDB(PULPL3TilingDB, ProfilingDoubleBufferingTilingMixIn): - pass diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingSB.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingSB.py deleted file mode 100644 index 8079516720..0000000000 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3TilingSB.py +++ /dev/null @@ -1,468 +0,0 @@ -# ---------------------------------------------------------------------- -# -# File: PULPL3TilingSB.py -# -# Last edited: 19.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -from collections import namedtuple -from typing import Dict, List, Literal, Optional, Tuple, Type - -import Deeploy.CommonExtensions.DataTypes as BasicDataTypes -from Deeploy.AbstractDataTypes import Immediate, PointerClass -from Deeploy.DeeployTypes import CodeSnippet, ConstantBuffer, ExecutionBlock, NetworkContext, NodeTemplate, \ - OperatorRepresentation -from Deeploy.Targets.PULPOpen.CodeTransformationPasses import AutoTransposeUtils -from Deeploy.Targets.PULPOpen.DataTypes import PULPStructDataTypes -from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import ProfilingSingleBufferingTilingMixIn, \ - SingleBufferingTilingMixIn, TilingMetaInfo -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme, \ - calculateRectangleOffset, minimizeRectangleDims - -_openTileLoopTemplate = NodeTemplate(""" - -// TILING LOOP -// for (int TILING_I=0; TILING_I<${numTiles}; TILING_I++){ -for (int TILING_I=${numTiles}[*${tileIdxPtr}]; TILING_I<${numTiles}[(*${tileIdxPtr})+1]; TILING_I++){ -""") - -_closeTileLoopTemplate = NodeTemplate(""" - -// CLOSE TILING LOOP -} -*${tileIdxPtr} += 1; - -""") - -_moveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -pi_cl_ram_copy_2d(get_ram_ptr(), ${stateReference}.pi_ram_addr, ${stateReference}.addr, ${stateReference}.size, ${stateReference}.stride, ${stateReference}.length, ${stateReference}.ext2loc, &${stateReference}); -// L3 TRANSFERS CANNOT BE CONCURRENT WITH CURRENT DRIVER -pi_cl_ram_copy_wait(&${stateReference}); - -""") - -_blockTileInTemplate = NodeTemplate(""" - -// BLOCKING IMPORT TILE ${innerTilePtr} -pi_cl_ram_copy_wait(&${stateReference}); - -""") - -_moveTileOutTemplate = NodeTemplate(""" - -// EXPORT TILE ${innerTilePtr} to ${outerTilePtr} -pi_cl_ram_copy_2d(get_ram_ptr(), ${stateReference}.pi_ram_addr, ${stateReference}.addr, ${stateReference}.size, ${stateReference}.stride, ${stateReference}.length, ${stateReference}.ext2loc, &${stateReference}); -// L3 TRANSFERS CANNOT BE CONCURRENT WITH CURRENT DRIVER -pi_cl_ram_copy_wait(&${stateReference}); - -""") - -_blockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -pi_cl_ram_copy_wait(&${stateReference}); - -""") - -_updateDMATransferStructTemplate = NodeTemplate(""" - -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.pi_ram_addr = ((char*)${extPtr}) + ${extOffsetPtr}[${tileNum}]; -${stateReference}.size = ${length1dPtr}[${tileNum}]; -${stateReference}.length = ${number1dPtr}[${tileNum}]; - -""") - -# ${stateReference}.number_of_2d_copies = ${number2dPtr}[${tileNum}]; - -_updateReferenceTemplate = NodeTemplate(""" - -// UPDATE VARIABLE ${reference} -*${reference} = ${baseReference}[${tileNum}]; -""") - -# ADD NUM TRANSFERS VARIABLE - -_DMAUpdate = namedtuple("_DMAUpdate", "extOffset locOffset length_1d_copy number_of_1d_copies number_of_2d_copies") - - -class PULPL3TilingSB(TilingCodeGeneration): - - _prefix = "TILING_REPLACED_" - - _openTileLoopTemplate = _openTileLoopTemplate - _closeTileLoopTemplate = _closeTileLoopTemplate - - _moveTileInTemplate = _moveTileInTemplate - _blockTileInTemplate = _blockTileInTemplate - - _moveTileOutTemplate = _moveTileOutTemplate - _blockTileOutTemplate = _blockTileOutTemplate - - _updateDMATransferStructTemplate = _updateDMATransferStructTemplate - _updateReferenceTemplate = _updateReferenceTemplate - - @property - def prefix(self): - return self._prefix + self.targetMemLevel + "_" - - def _DMAStructName(self, tensorName: str, nodeName: str) -> str: - return f"{self.prefix}_DMA_{nodeName}_{tensorName}" - - @classmethod - def _generatePointerUpdates(cls, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - loadSchedule: List[Dict[str, HyperRectangle]], - tilingSchedule: TilingSchedule) -> Dict[str, _DMAUpdate]: - updateDict = {} - deltaOffsets = {} - - for idx, loadStep in enumerate(loadSchedule): - for stepIdx, (key, rect) in enumerate(loadStep.items()): - - if key in tilingSchedule.outputBaseOffsets.keys(): - baseOffsets = tilingSchedule.outputBaseOffsets[key] - direction = "FromL2" - else: - baseOffsets = tilingSchedule.inputBaseOffsets[key] - direction = "ToL2" - - if key not in updateDict.keys(): - updateDict[key] = [] - if key not in deltaOffsets.keys(): - deltaOffsets[key] = 0 - - referenceBuffer = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - l1Buffer = ctxt.lookup(operatorRepresentation[key]) - - struct = cls._rectToDMAStruct(ctxt, rect, direction, l1Buffer.name, l1Buffer._referenceName) - accOffset = calculateRectangleOffset(rect, referenceBuffer) - - length_1d_copy = struct.value['size'].value - number_of_1d_copies = struct.value['length'].value - - lIdx = idx % len(baseOffsets) - - sol = _DMAUpdate(accOffset, baseOffsets[lIdx], length_1d_copy, number_of_1d_copies, 0) - - deltaOffsets[key] = accOffset - updateDict[key].append(sol) - - return updateDict - - @classmethod - def _rectToDMAStruct(cls, ctxt: NetworkContext, rectangle: HyperRectangle, direction: Literal["ToL2", "FromL2"], - L1Name: str, L2Name: str) -> PULPStructDataTypes.pi_cl_ram_req_t: - - referenceBuffer = ctxt.lookup(L2Name) - - rect, referenceRect = minimizeRectangleDims(rectangle, referenceBuffer) - assert len(rect.dims) <= 2, "PULP: Only 2D transfers are supported!" - - if direction == "ToL2": - _dir = 1 - else: - _dir = 0 - - length_1d_copy = rect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - - if len(rect.dims) > 1: - number_of_1d_copies = rect.dims[-2] - stride_1d = referenceRect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - else: - number_of_1d_copies = 1 - stride_1d = 0 - - struct = PULPStructDataTypes.pi_cl_ram_req_t( - { - "pi_ram_addr": referenceBuffer.name, - "addr": L1Name, - "stride": stride_1d, - "length": length_1d_copy, - "size": number_of_1d_copies * length_1d_copy, - "ext2loc": _dir, - "is_2d": 1 - }, ctxt) - - return struct - - def _hoistConstantAndReference(self, - ctxt: NetworkContext, - constBuf: ConstantBuffer, - operatorRepresentation: OperatorRepresentation, - nodeName: str, - operatorRepresentationName: str, - immediateType: Optional[Type[Immediate]] = None) -> Tuple[NetworkContext, Dict]: - if immediateType is None: - _type = PointerClass(BasicDataTypes.int32_t) - else: - _type = PointerClass(immediateType) - - constBuf._users = [nodeName] - constBuf._memoryLevel = self.targetMemLevel - - refName = ctxt.hoistConstantAndReference(constBuf, _type) - - operatorRepresentation[operatorRepresentationName] = refName - - return ctxt, operatorRepresentation - - def _hoistDMAUpdates(self, ctxt: NetworkContext, tensorName: str, updateList: List[_DMAUpdate], - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict]: - - operatorRepresentation = operatorRepresentation.copy() - - nodeName = operatorRepresentation['nodeName'] - - offsetList = [] - len1dList = [] - num1dList = [] - num2dList = [] - for update in updateList: - offsetList.append(int(update.extOffset)) - len1dList.append(int(update.length_1d_copy)) - num1dList.append(int(update.number_of_1d_copies)) - num2dList.append(int(update.number_of_2d_copies)) - - dmaName = self._DMAStructName(tensorName, nodeName) - operatorRepresentation['stateReference'] = dmaName - operatorRepresentation['tileNum'] = "TILING_I" - operatorRepresentation['extPtr'] = ctxt.lookup(operatorRepresentation[tensorName])._referenceName - - namePrefix = self.prefix + f"{nodeName}_{tensorName}" - - name = namePrefix + "_offset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], offsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'extOffsetPtr') - - name = namePrefix + "_length_1d_copy" - cb = ctxt.ConstantBuffer(name, [len(updateList)], len1dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'length1dPtr', - PULPStructDataTypes.pi_cl_ram_req_t.structTypeDict['size']) - - name = namePrefix + "_number_of_1d_copies" - cb = ctxt.ConstantBuffer(name, [len(updateList)], num1dList) - ctxt, operatorRepresentation = self._hoistConstantAndReference( - ctxt, cb, operatorRepresentation, nodeName, 'number1dPtr', - PULPStructDataTypes.pi_cl_ram_req_t.structTypeDict['length']) - - return ctxt, operatorRepresentation - - def _generateEgressPointerUpdates( - self, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, - tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateIngressPointerUpdates( - self, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.inputLoadSchedule, - tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateVariableUpdates(self, tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, - ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> List[CodeSnippet]: - - updates = [] - - for key in variableReplacement.perTileReplacements.keys(): - - buf = ctxt.lookup(operatorRepresentation[key]) - reference = str(buf._instance) - - updates.append( - CodeSnippet(self._updateReferenceTemplate, { - "reference": reference, - "tileNum": "TILING_I", - "baseReference": buf._referenceName - })) - - return updates - - def _generateDMACode(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - loadSchedule: List[Dict[str, HyperRectangle]], - direction: Literal["ToL2", "FromL2"]) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - DMATransferCalls = [] - DMAWaitStatements = [] - - allNumTransfers = AutoTransposeUtils.allNumTransfers(ctxt, operatorRepresentation, loadSchedule, direction) - - transferNodeRep = {} - - loadStep = loadSchedule[0] - - for idx, (key, rectangle) in enumerate(loadStep.items()): - - externalPtr = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - internalPtr = ctxt.lookup(operatorRepresentation[key]) - - tensorName = key - nodeName = operatorRepresentation['nodeName'] - dmaName = self._DMAStructName(tensorName, nodeName) - - transferNodeRep = { - **transferNodeRep, - **{ - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName - } - } - - struct = self._rectToDMAStruct(ctxt, rectangle, direction, internalPtr.name, externalPtr.name) - transferNodeRep["stateStruct"] = struct - _ = ctxt.hoistStruct(struct, dmaName, PULPStructDataTypes.pi_cl_ram_req_t) - ctxt.lookup(dmaName)._users += [operatorRepresentation['nodeName']] - - DMATransferCalls.append(CodeSnippet(self._moveTileInTemplate, transferNodeRep)) - - DMAWaitStatements.append(CodeSnippet(self._blockTileInTemplate, transferNodeRep)) - - return DMATransferCalls, DMAWaitStatements - - def _generateIngressDMACode( - self, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - importLoadStep = tilingSchedule.inputLoadSchedule - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateDMACode(ctxt, operatorRepresentation, - importLoadStep, "ToL2") - return ingressDMATransferCalls, ingressDMAWaitStatements - - def _generateEgressDMACode( - self, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - exportLoadStep = tilingSchedule.outputLoadSchedule - egressDMATransferCalls, egressDMAWaitStatements = self._generateDMACode(ctxt, operatorRepresentation, - exportLoadStep, "FromL2") - - return egressDMATransferCalls, egressDMAWaitStatements - - def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, - nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, - variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - tileIdxPtr = self._hoistTileIdxPtr(ctxt, operatorRepresentation) - - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateIngressDMACode( - tilingSchedule, ctxt, operatorRepresentation) - - egressDMATransferCalls, egressDMAWaitStatements = self._generateEgressDMACode( - tilingSchedule, ctxt, operatorRepresentation) - - ctxt, ingressDMAUpdates = self._generateIngressPointerUpdates(tilingSchedule, ctxt, operatorRepresentation) - ctxt, egressDMAUpdates = self._generateEgressPointerUpdates(tilingSchedule, ctxt, operatorRepresentation) - - setupStatements: List[CodeSnippet] = [] - teardownStatements: List[CodeSnippet] = [] - variableUpdates: List[CodeSnippet] = [] - - openLoopStatement = [ - CodeSnippet(self._openTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - closeLoopStatement = [ - CodeSnippet(self._closeTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - metaInfo = TilingMetaInfo(nodeName = operatorRepresentation['nodeName'] + "_L3", - nodeOps = operatorRepresentation['nodeOps'], - numTiles = len(tilingSchedule.outputLoadSchedule), - tileIdxVar = "TILING_I", - kernelLevelTiling = False) - - newExecutionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements, ingressDMAUpdates, - egressDMATransferCalls, egressDMAWaitStatements, - egressDMAUpdates, variableUpdates, openLoopStatement, - closeLoopStatement, setupStatements, teardownStatements) - - return ctxt, newExecutionBlock, True - - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == 1: - return ctxt, executionBlock, False - - operatorRepresentation["numTiles"] = self._hoistNumTiles(ctxt, operatorRepresentation['nodeName'], - tilingSchedules) - - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) - - -class PULPL3TilingGenerationSB(PULPL3TilingSB, SingleBufferingTilingMixIn): - pass - - -class ProfilingPULPL3TilingGenerationSB(PULPL3TilingSB, ProfilingSingleBufferingTilingMixIn): - pass diff --git a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py new file mode 100644 index 0000000000..c74b4da7ed --- /dev/null +++ b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py @@ -0,0 +1,53 @@ +import math +from typing import Dict, Tuple + +from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer +from Deeploy.TilingExtension.AsyncDma import AsyncDma, BlockingDmaFromAsyncDmaAdapter, DmaDirection, Future, \ + PerTensorWaitingStrategy + + +class L3DmaFuture(Future): + + _initTemplate = NodeTemplate("pi_cl_ram_req_t ${name};") + _deinitTemplate = NodeTemplate("") + _waitTemplate = NodeTemplate("pi_cl_ram_copy_wait(&${name});") + + +class L3Dma(AsyncDma): + + _transferTemplates = { + 2: + NodeTemplate( + "pi_cl_ram_copy_2d(get_ram_ptr(), ${ext}, ${loc}, ${transfer_size}, ${stride}, ${length}, ${ext2loc}, &${future});" + ) + } + _waitingStrategy = PerTensorWaitingStrategy(L3DmaFuture) + + def __init__(self, transferTemplates: Dict[int, NodeTemplate] = _transferTemplates) -> None: + super().__init__(transferTemplates) + + def checkTransfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection) -> None: + super().checkTransfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction) + assert strideExt[-1] == 1, \ + "Mchan supports only contigous transfers of the innermost dimension for external memory" + assert strideLoc[0] == shape[1] and strideLoc[1] == 1, \ + f"Mchan supports only contigous transfers for local memory. Received local shape: {shape}, stride: {strideLoc}" + + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], + strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, + future: Future) -> OperatorRepresentation: + operatorRepresentation = super().transferOpRepr(externalBuffer, localBuffer, shape, strideExt, strideLoc, + direction, future) + operatorRepresentation.update({ + "ext2loc": 1 if direction == "ExternalToLocal" else 0, + "transfer_size": math.prod(shape), + "length": shape[1], + "stride": strideExt[0], + }) + return operatorRepresentation + + +# LMACAN: It's a hack because the driver is now working correctly +l3DmaHack = BlockingDmaFromAsyncDmaAdapter(L3Dma()) diff --git a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py new file mode 100644 index 0000000000..0f2b77a03d --- /dev/null +++ b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py @@ -0,0 +1,66 @@ +import math +from typing import Dict, Tuple + +from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer +from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future, TensorGroupWaitingStrategy + + +class MchanChannelFuture(Future): + + _initTemplate = NodeTemplate("uint32_t ${name} = mchan_channel_alloc();") + _deinitTemplate = NodeTemplate("mchan_channel_free(${name});") + _waitTemplate = NodeTemplate("mchan_channel_wait(${name});") + + +class MchanDma(AsyncDma): + + _transferTemplates = { + 1: NodeTemplate("mchan_transfer_1d(${cmd}, ${loc}, ${ext});"), + 2: NodeTemplate("mchan_transfer_2d_ext_strided(${cmd}, ${loc}, ${ext}, ${size_1d}, ${stride_2d});"), + } + _waitingStrategy = TensorGroupWaitingStrategy(MchanChannelFuture, "channel_id") + + def __init__(self, transferTemplates: Dict[int, NodeTemplate] = _transferTemplates) -> None: + super().__init__(transferTemplates) + + def checkTransfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection) -> None: + super().checkTransfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction) + + transferRank = len(shape) + assert strideExt[ + -1] == 1, "Mchan supports only contigous transfers of the innermost dimension for external memory" + if transferRank == 1: + assert strideLoc[0] == 1, "Mchan supports only contigous transfers for local memory" + else: + assert strideLoc[0] == shape[1] and strideLoc[ + 1] == 1, "Mchan supports only contigous transfers for local memory" + + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], + strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, + future: Future) -> OperatorRepresentation: + operatorRepresentation = super().transferOpRepr(externalBuffer, localBuffer, shape, strideExt, strideLoc, + direction, future) + + transferRank = len(shape) + + mchanFlags = 0 + mchanFlags += (1 << 0) if direction == "ExternalToLocal" else 0 # direction + mchanFlags += (1 << 1) # increment addresses + mchanFlags += (1 << 2) if transferRank == 2 else 0 # 2d transfer + mchanFlags += (1 << 3) # event enable + + mchanTransferSize = math.prod(shape) + mchanTransferSizeBits = math.ceil(math.log2(mchanTransferSize)) + assert mchanTransferSizeBits <= 17, ( + "The transfer size is not representable with 17 bits. " + f"Received transfer size {mchanTransferSize} that requires {mchanTransferSizeBits}") + + operatorRepresentation["cmd"] = (mchanFlags << 17) + mchanTransferSize + + if transferRank == 2: + operatorRepresentation["size_1d"] = shape[1] + operatorRepresentation["stride_2d"] = strideExt[0] + + return operatorRepresentation diff --git a/Deeploy/Targets/PULPOpen/Platform.py b/Deeploy/Targets/PULPOpen/Platform.py index 93e42b77d0..2fded86717 100644 --- a/Deeploy/Targets/PULPOpen/Platform.py +++ b/Deeploy/Targets/PULPOpen/Platform.py @@ -253,8 +253,8 @@ class PULPStructBuffer(StructBuffer): # SCHEREMO: stdint is included before pulp_nn_kernels.h because it is supposed to be included in there, but isn't... _includeList = [ - "pmsis.h", "stdint.h", "pulp_nn_kernels.h", "DeeployBasicMath.h", "DeeployPULPMath.h", "dory_dma.h", "dory_mem.h", - "bsp/ram.h", "pulp_core.h" + "pmsis.h", "stdint.h", "pulp_nn_kernels.h", "DeeployBasicMath.h", "DeeployPULPMath.h", "mchan_siracusa.h", + "dory_mem.h", "bsp/ram.h", "pulp_core.h" ] diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py index 7f8a456265..4206be3390 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py @@ -117,9 +117,13 @@ def serializeTilingSolution( addrNames = ['A', 'B', 'mul', 'C', 'data_out'] inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) - varA = operatorRepresentation['A'] + transA = operatorRepresentation['transA'] + transB = operatorRepresentation['transB'] - NSize = ctxt.lookup(varA).shape[-1] + buffA = ctxt.lookup(operatorRepresentation['A']) + buffB = ctxt.lookup(operatorRepresentation['B']) + + NSize = buffA.shape[-1] NOffset = 0 inputACubes = [] @@ -151,8 +155,51 @@ def serializeTilingSolution( replacements["O"].append(OSize) replacements["batch"].append(BSize) - ACube = HyperRectangle((BatchOffset, BOffset, MOffset, NOffset), (BatchSize, BSize, MSize, NSize)) - BCube = HyperRectangle((BatchOffset, BOffset, OOffset, NOffset), (BatchSize, BSize, OSize, NSize)) + if transA == 0: + AMatrixOffsets = (MOffset, NOffset) + AMatrixShape = (MSize, NSize) + else: + AMatrixOffsets = (NOffset, MOffset) + AMatrixShape = (NSize, MSize) + + if transB == 0: + BMatrixOffsets = (NOffset, OOffset) + BMatrixShape = (NSize, OSize) + else: + BMatrixOffsets = (OOffset, NOffset) + BMatrixShape = (OSize, NSize) + + if len(buffA.shape) == 2: + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + elif len(buffA.shape) == 3: + ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) + else: + ACube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + AMatrixOffsets, + ( + BatchSize, + BSize, + ) + AMatrixShape, + ) + + if len(buffB.shape) == 2: + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) + elif len(buffB.shape) == 3: + BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) + else: + BCube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + BMatrixOffsets, + ( + BatchSize, + BSize, + ) + BMatrixShape, + ) RequantCube = HyperRectangle((OOffset,), (OSize,)) @@ -301,13 +348,14 @@ def serializeTilingSolution( transA = operatorRepresentation['transA'] transB = operatorRepresentation['transB'] - varA = operatorRepresentation['A'] - varB = operatorRepresentation['B'] + buffA = ctxt.lookup(operatorRepresentation['A']) + buffB = ctxt.lookup(operatorRepresentation['B']) + buffC = ctxt.lookup(operatorRepresentation['C']) if transA == 0: - NSize = ctxt.lookup(varA).shape[-1] + NSize = buffA.shape[-1] else: - NSize = ctxt.lookup(varA).shape[-2] + NSize = buffA.shape[-2] NOffset = 0 @@ -340,16 +388,60 @@ def serializeTilingSolution( replacements["batch"].append(BSize) if transA == 0: - ACube = HyperRectangle((BatchOffset, BOffset, MOffset, NOffset), (BatchSize, BSize, MSize, NSize)) + AMatrixOffsets = (MOffset, NOffset) + AMatrixShape = (MSize, NSize) else: - ACube = HyperRectangle((BatchOffset, BOffset, NOffset, MOffset), (BatchSize, BSize, NSize, MSize)) + AMatrixOffsets = (NOffset, MOffset) + AMatrixShape = (NSize, MSize) if transB == 0: - BCube = HyperRectangle((BatchOffset, BOffset, NOffset, OOffset), (BatchSize, BSize, NSize, OSize)) + BMatrixOffsets = (NOffset, OOffset) + BMatrixShape = (NSize, OSize) else: - BCube = HyperRectangle((BatchOffset, BOffset, OOffset, NOffset), (BatchSize, BSize, OSize, NSize)) + BMatrixOffsets = (OOffset, NOffset) + BMatrixShape = (OSize, NSize) - CCube = HyperRectangle(cube.offset, cube.dims) + if len(buffA.shape) == 2: + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + elif len(buffA.shape) == 3: + ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) + else: + ACube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + AMatrixOffsets, + ( + BatchSize, + BSize, + ) + AMatrixShape, + ) + + if len(buffB.shape) == 2: + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) + elif len(buffB.shape) == 3: + BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) + else: + BCube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + BMatrixOffsets, + ( + BatchSize, + BSize, + ) + BMatrixShape, + ) + + CMatrixOffsets = (MOffset, OOffset) + CMatrixShape = (MSize, OSize) + + if len(buffC.shape) == 2: + CCube = HyperRectangle(CMatrixOffsets, CMatrixShape) + elif len(buffC.shape) == 3: + CCube = HyperRectangle((BatchOffset,) + CMatrixOffsets, (BatchSize,) + CMatrixShape) + else: + CCube = HyperRectangle((BatchOffset, BOffset) + CMatrixOffsets, (BatchSize, BSize) + CMatrixShape) inputACubes.append(ACube) inputBCubes.append(BCube) diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py index 2b5d284159..cae635b5fc 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py @@ -112,9 +112,10 @@ def serializeTilingSolution( inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) - varA = operatorRepresentation['A'] + buffA = ctxt.lookup(operatorRepresentation['A']) + buffB = ctxt.lookup(operatorRepresentation['B']) - NSize = ctxt.lookup(varA).shape[-1] + NSize = buffA.shape[-1] NOffset = 0 inputACubes = [] @@ -144,8 +145,43 @@ def serializeTilingSolution( replacements["O"].append(OSize) replacements["batch"].append(BSize) - ACube = HyperRectangle((BatchOffset, BOffset, MOffset, NOffset), (BatchSize, BSize, MSize, NSize)) - BCube = HyperRectangle((BatchOffset, BOffset, NOffset, OOffset), (BatchSize, BSize, NSize, OSize)) + AMatrixOffsets = (MOffset, NOffset) + AMatrixShape = (MSize, NSize) + + BMatrixOffsets = (NOffset, OOffset) + BMatrixShape = (NSize, OSize) + + if len(buffA.shape) == 2: + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + elif len(buffA.shape) == 3: + ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) + else: + ACube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + AMatrixOffsets, + ( + BatchSize, + BSize, + ) + AMatrixShape, + ) + + if len(buffB.shape) == 2: + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) + elif len(buffB.shape) == 3: + BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) + else: + BCube = HyperRectangle( + ( + BatchOffset, + BOffset, + ) + BMatrixOffsets, + ( + BatchSize, + BSize, + ) + BMatrixShape, + ) inputACubes.append(ACube) inputBCubes.append(BCube) diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py index 343c4970eb..cec95f671d 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py @@ -114,7 +114,7 @@ def serializeTilingSolution( replacements['num_classes'].append(num_classes) replacements['batch'].append(batch) - labelCube = HyperRectangle((0, cube.offset[0]), (1, batch)) + labelCube = HyperRectangle((cube.offset[0],), (batch,)) inputlabelCubes.append(labelCube) inputLoadSchedule = [] diff --git a/Deeploy/Targets/Snitch/Bindings.py b/Deeploy/Targets/Snitch/Bindings.py index 37f7800d6b..391c64af81 100644 --- a/Deeploy/Targets/Snitch/Bindings.py +++ b/Deeploy/Targets/Snitch/Bindings.py @@ -36,11 +36,13 @@ from Deeploy.Targets.Generic.TypeCheckers import AddChecker, GEMMChecker, RQAddChecker, SoftmaxChecker, iNoNormChecker from Deeploy.Targets.Snitch.CodeTransformationPasses import SnitchClusterTiling, SnitchCoreFilterPass, \ SnitchProfileExecutionBlockPass, SnitchSynchCoresPass +from Deeploy.Targets.Snitch.DMA.SnitchDma import SnitchDma from Deeploy.Targets.Snitch.Templates import AddTemplate, FloatGemmTemplate, RQAddTemplate, iSoftmaxTemplate from Deeploy.Targets.Snitch.Templates.FloatSoftmaxTemplate import FloatSoftmax_Template from Deeploy.Targets.Snitch.Templates.GemmTemplate import SnitchGemm_Template from Deeploy.Targets.Snitch.Templates.RqGemmTemplate import SnitchRqGemm_Template -from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement +from Deeploy.TilingExtension.CodeTransformationPasses.TilingVariableReplacement import TilingVariableReplacement, \ + TilingVariableReplacementUpdate TilingCallClosure = partial(ClosureGeneration, closureSuffix = "_tiling_closure") MemoryAwareFunctionCallClosure = partial(MemoryAwareClosureGeneration, @@ -60,7 +62,8 @@ TilingVariableReplacement("L1"), TilingCallClosure(writeback = False), SnitchSynchCoresPass(), - SnitchClusterTiling("L1"), + TilingVariableReplacementUpdate("L1"), + SnitchClusterTiling("L2", "L1", SnitchDma()), ArgumentStructGeneration(), MemoryManagementGeneration("L1"), MemoryAwareFunctionCallClosure(writeback = False, generateStruct = True), diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py index ce513a5355..71268d0a6d 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py @@ -26,24 +26,37 @@ from typing import Tuple from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity +from Deeploy.TilingExtension.AsyncDma import AsyncDma +from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ + DoubleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ + SingleBufferingTilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ + SingleBufferingTilingMixIn -from .SnitchClusterTilingSB import SnitchClusterTilingGenerationSB + +class SnitchClusterTilingSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): + pass + + +class SnitchClusterTilingDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): + pass class SnitchClusterTiling(CodeTransformationPass): - def __init__(self, targetMemLevel: str): - self.SB = SnitchClusterTilingGenerationSB(targetMemLevel) + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): + self.SB = SnitchClusterTilingSB(externalMemory, localMemory, dma) + self.DB = SnitchClusterTilingDB(externalMemory, localMemory, dma) def apply(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: - if verbose.tilingProfiling: raise NotImplementedError("Profiling not implemented for L2") - # ctxt, executionBlock = self.profilingSB.apply(ctxt, executionBlock, name) - else: - ctxt, executionBlock = self.SB.apply(ctxt, executionBlock, name) + + ctxt, executionBlock = self.SB.apply(ctxt, executionBlock, name) + ctxt, executionBlock = self.DB.apply(ctxt, executionBlock, name) return ctxt, executionBlock diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTilingSB.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTilingSB.py deleted file mode 100644 index 8e31ee2627..0000000000 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTilingSB.py +++ /dev/null @@ -1,520 +0,0 @@ -# ---------------------------------------------------------------------- -# -# File: SnitchClusterTilingSB.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -from collections import namedtuple -from typing import Dict, List, Literal, Tuple - -from Deeploy.DeeployTypes import CodeSnippet, ExecutionBlock, NetworkContext, NodeTemplate, OperatorRepresentation -from Deeploy.Targets.Snitch.DataTypes import Snitch_DMA_copy -from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import SingleBufferingTilingMixIn, TilingMetaInfo -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme, \ - calculateRectangleOffset, minimizeRectangleDims - -_openTileLoopTemplate = NodeTemplate(""" - -// TILING LOOP -for (int TILING_I=${numTiles}[*${tileIdxPtr}]; TILING_I<${numTiles}[(*${tileIdxPtr})+1]; TILING_I++){ -""") - -_closeTileLoopTemplate = NodeTemplate(""" - -// CLOSE TILING LOOP -} -*${tileIdxPtr} += 1; - -""") - -_moveTileInTemplate = NodeTemplate(""" - -// IMPORT TILE ${innerTilePtr} from ${outerTilePtr} -if(snrt_is_dm_core()){ - ${stateReference}.tid = snrt_dma_start_2d(${stateReference}.dst, - ${stateReference}.src, - ${stateReference}.size, - ${stateReference}.dst_stride, - ${stateReference}.src_stride, - ${stateReference}.repeat); -} -""") - -_iteratedMoveTileInTemplate = NodeTemplate(""" - -""") - -_blockTileInTemplate = NodeTemplate(""" - -// BLOCKING IMPORT TILE ${innerTilePtr} -if(snrt_is_dm_core()){ - // snrt_dma_wait(${stateReference}.tid); - snrt_dma_wait_all(); -} -""") - -_moveTileOutTemplate = NodeTemplate(""" - -// EXPORT TILE ${innerTilePtr} to ${outerTilePtr} -if(snrt_is_dm_core()){ - ${stateReference}.tid = snrt_dma_start_2d(${stateReference}.dst, - ${stateReference}.src, - ${stateReference}.size, - ${stateReference}.dst_stride, - ${stateReference}.src_stride, - ${stateReference}.repeat); -} -""") - -_blockTileOutTemplate = NodeTemplate(""" - -// BLOCKING EXPORT TILE ${innerTilePtr} -if(snrt_is_dm_core()){ - //snrt_dma_wait(${stateReference}.tid); - snrt_dma_wait_all(); -} -""") - -_updateDMATransferStructTemplate = NodeTemplate(""" - -// UPDATE DMA STRUCT ${stateReference} -${stateReference}.dst = ((char*)${dstPtr}) + ${dstOffsetPtr}[${tileNum}]; -${stateReference}.src = ((char*)${srcPtr}) + ${srcOffsetPtr}[${tileNum}]; -${stateReference}.size = ${sizePtr}[${tileNum}]; -${stateReference}.dst_stride = ${dstStridePtr}[${tileNum}]; -${stateReference}.src_stride = ${srcStridePtr}[${tileNum}]; -${stateReference}.repeat = ${repeatPtr}[${tileNum}]; -""") - -_updateReferenceTemplate = NodeTemplate(""" - -// UPDATE VARIABLE ${reference} -*${reference} = ${baseReference}[${tileNum}]; -""") - -_DMAUpdate = namedtuple("_DMAUpdate", "dst src size dst_stride src_stride repeat tid direction") - - -class SnitchClusterTilingSB(TilingCodeGeneration): - - _prefix = "TILING_REPLACED_" - - _openTileLoopTemplate = _openTileLoopTemplate - _closeTileLoopTemplate = _closeTileLoopTemplate - - _moveTileInTemplate = _moveTileInTemplate - _iteratedMoveTileInTemplate = _iteratedMoveTileInTemplate - _blockTileInTemplate = _blockTileInTemplate - - _moveTileOutTemplate = _moveTileOutTemplate - _blockTileOutTemplate = _blockTileOutTemplate - - _updateDMATransferStructTemplate = _updateDMATransferStructTemplate - _updateReferenceTemplate = _updateReferenceTemplate - - @property - def prefix(self): - return self._prefix + self.targetMemLevel + "_" - - def _DMAStructName(self, tensorName: str, nodeName: str) -> str: - return f"{self.prefix}_DMA_{nodeName}_{tensorName}" - - @classmethod - def _generatePointerUpdates(cls, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - loadSchedule: List[Dict[str, - HyperRectangle]], nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedule: TilingSchedule) -> Dict[str, _DMAUpdate]: - updateDict = {} - deltaOffsets = {} - - for idx, loadStep in enumerate(loadSchedule): - for _, (key, rect) in enumerate(loadStep.items()): - - if key in tilingSchedule.outputBaseOffsets.keys(): - baseOffsets = tilingSchedule.outputBaseOffsets[key] - direction = "FromL1" - else: - baseOffsets = tilingSchedule.inputBaseOffsets[key] - direction = "ToL1" - - if key not in updateDict.keys(): - updateDict[key] = [] - if key not in deltaOffsets.keys(): - deltaOffsets[key] = 0 - - referenceBuffer = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - l1Buffer = ctxt.lookup(operatorRepresentation[key]) - - finalMemoryLevel = TilingCodeGeneration.isFinalMemoryLevel(nodeMemoryConstraint, l1Buffer) - - struct = cls._rectToDMAStruct(ctxt, rect, direction, l1Buffer.name, l1Buffer._referenceName, - finalMemoryLevel) - accOffset = calculateRectangleOffset(rect, referenceBuffer) - - lIdx = idx % len(baseOffsets) - - if direction == "ToL1": - src = accOffset - dst = baseOffsets[lIdx] - else: - src = baseOffsets[lIdx] - dst = accOffset - - size = struct.value['size'].value - dst_stride = struct.value['dst_stride'].value - src_stride = struct.value['src_stride'].value - repeat = struct.value['repeat'].value - tid = struct.value['tid'].value - - sol = _DMAUpdate(dst, src, size, dst_stride, src_stride, repeat, tid, direction) - - deltaOffsets[key] = accOffset - updateDict[key].append(sol) - - return updateDict - - @classmethod - def _rectToDMAStruct(cls, ctxt: NetworkContext, rectangle: HyperRectangle, direction: Literal["ToL1", "FromL1"], - L1Name: str, L2Name: str, finalMemoryLevel: bool) -> Snitch_DMA_copy: - - referenceBuffer = ctxt.lookup(L2Name) - - rect, referenceRect = minimizeRectangleDims(rectangle, referenceBuffer) - assert len(rect.dims) <= 3, "Snitch's iDMA only 2D transfers are supported!" - - if direction == "FromL1": - _src = L1Name - _dst = referenceBuffer.name - else: - _src = referenceBuffer.name - _dst = L1Name - - transfer_size = rect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - - src_stride = 0 - dst_stride = 0 - repeat = 1 - if len(rect.dims) > 1: - repeat = rect.dims[-2] - if direction == "ToL1": - dst_stride = rect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - src_stride = referenceRect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - else: - dst_stride = referenceRect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - src_stride = rect.dims[-1] * (referenceBuffer._type.referencedType.typeWidth // 8) - - struct = Snitch_DMA_copy( - { - "dst": _dst, - "src": _src, - "size": transfer_size, - "dst_stride": dst_stride, - "src_stride": src_stride, - "repeat": repeat, - "tid": 0 - }, ctxt) - - return struct - - def _hoistDMAUpdates(self, ctxt: NetworkContext, tensorName: str, updateList: List[_DMAUpdate], - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict]: - - operatorRepresentation = operatorRepresentation.copy() - - nodeName = operatorRepresentation['nodeName'] - - dstList = [] - srcList = [] - sizeList = [] - dstStrideList = [] - srcStideList = [] - repeatList = [] - for update in updateList: - dstList.append(int(update.dst)) - srcList.append(int(update.src)) - sizeList.append(int(update.size)) - dstStrideList.append(int(update.dst_stride)) - srcStideList.append(int(update.src_stride)) - repeatList.append(int(update.repeat)) - - dmaName = self._DMAStructName(tensorName, nodeName) - - operatorRepresentation['stateReference'] = dmaName - operatorRepresentation['tileNum'] = "TILING_I" - - if updateList[0].direction == "ToL1": - operatorRepresentation['dstPtr'] = ctxt.lookup(operatorRepresentation[tensorName]).name - operatorRepresentation['srcPtr'] = ctxt.lookup(operatorRepresentation[tensorName])._referenceName - - dstOffsetList = [0] * len(updateList) - srcOffsetList = [srcList[i] - srcList[0] for i in range(0, len(srcList))] - # srcOffsetList = [0] + [sum(sizeList[:i+1]) for i in range(0, len(sizeList)-1)] - else: - operatorRepresentation['dstPtr'] = ctxt.lookup(operatorRepresentation[tensorName])._referenceName - operatorRepresentation['srcPtr'] = ctxt.lookup(operatorRepresentation[tensorName]).name - - dstOffsetList = [dstList[i] - dstList[0] for i in range(0, len(dstList))] - # dstOffsetList = [0] + [sum(sizeList[:i+1]) for i in range(0, len(sizeList)-1)] - srcOffsetList = [0] * len(updateList) - - namePrefix = self.prefix + f"{nodeName}_{tensorName}" - - name = namePrefix + "_dst_offset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], dstOffsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'dstOffsetPtr') - - name = namePrefix + "_src_offset" - cb = ctxt.ConstantBuffer(name, [len(updateList)], srcOffsetList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'srcOffsetPtr') - - name = namePrefix + "_size" - cb = ctxt.ConstantBuffer(name, [len(updateList)], sizeList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'sizePtr', - Snitch_DMA_copy.structTypeDict['size']) - - name = namePrefix + "_dst_stride" - cb = ctxt.ConstantBuffer(name, [len(updateList)], dstStrideList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'dstStridePtr', - Snitch_DMA_copy.structTypeDict['dst_stride']) - - name = namePrefix + "_src_stride" - cb = ctxt.ConstantBuffer(name, [len(updateList)], srcStideList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'srcStridePtr', - Snitch_DMA_copy.structTypeDict['src_stride']) - - name = namePrefix + "_repeat" - cb = ctxt.ConstantBuffer(name, [len(updateList)], repeatList) - ctxt, operatorRepresentation = self._hoistConstantAndReference(ctxt, cb, operatorRepresentation, nodeName, - 'repeatPtr', - Snitch_DMA_copy.structTypeDict['repeat']) - - return ctxt, operatorRepresentation - - def _generateEgressPointerUpdates( - self, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, - nodeMemoryConstraint, tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateIngressPointerUpdates( - self, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, List[CodeSnippet]]: - - updates = [] - newCtxt = ctxt.copy() - - updateDict = self._generatePointerUpdates(ctxt, operatorRepresentation, tilingSchedule.inputLoadSchedule, - nodeMemoryConstraint, tilingSchedule) - - for key, updateList in updateDict.items(): - - newCtxt, newNodeRep = self._hoistDMAUpdates(newCtxt, key, updateList, operatorRepresentation) - updates.append(CodeSnippet(self._updateDMATransferStructTemplate, newNodeRep)) - - return newCtxt, updates - - def _generateVariableUpdates(self, tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, - ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> List[CodeSnippet]: - - updates = [] - - for key in variableReplacement.perTileReplacements.keys(): - - buf = ctxt.lookup(operatorRepresentation[key]) - reference = str(buf._instance) - - updates.append( - CodeSnippet(self._updateReferenceTemplate, { - "reference": reference, - "tileNum": "TILING_I", - "baseReference": buf._referenceName - })) - - return updates - - def _generateDMACode(self, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation, loadSchedule: List[Dict[str, HyperRectangle]], - direction: Literal["ToL1", "FromL1"]) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - DMATransferCalls = [] - DMAWaitStatements = [] - transferNodeRep = {} - - loadStep = loadSchedule[0] - - for idx, (key, rectangle) in enumerate(loadStep.items()): - - permName = f"in{idx}_perm" - - externalPtr = ctxt.lookup(ctxt.lookup(operatorRepresentation[key])._referenceName) - internalPtr = ctxt.lookup(operatorRepresentation[key]) - - tensorName = key - nodeName = operatorRepresentation['nodeName'] - dmaName = self._DMAStructName(tensorName, nodeName) - - transferNodeRep = { - **transferNodeRep, - **{ - 'innerTilePtr': str(internalPtr._instance), - "outerTilePtr": str(externalPtr._instance), - "stateReference": dmaName - } - } - - finalMemoryLevel = TilingCodeGeneration.isFinalMemoryLevel(nodeMemoryConstraint, internalPtr) - struct = self._rectToDMAStruct(ctxt, rectangle, direction, internalPtr.name, externalPtr.name, - finalMemoryLevel) - - transferNodeRep["stateStruct"] = struct - _ = ctxt.hoistStruct(struct, dmaName, Snitch_DMA_copy) - ctxt.lookup(dmaName)._users += [operatorRepresentation['nodeName']] - - if permName in operatorRepresentation and direction == "ToL1": - - DMATransferCalls.append(CodeSnippet(self._iteratedMoveTileInTemplate, transferNodeRep)) - else: - DMATransferCalls.append(CodeSnippet(self._moveTileInTemplate, transferNodeRep)) - - DMAWaitStatements.append(CodeSnippet(self._blockTileInTemplate, transferNodeRep)) - - return DMATransferCalls, DMAWaitStatements - - def _generateIngressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - importLoadStep = tilingSchedule.inputLoadSchedule - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateDMACode(nodeMemoryConstraint, ctxt, - operatorRepresentation, - importLoadStep, "ToL1") - return ingressDMATransferCalls, ingressDMAWaitStatements - - def _generateEgressDMACode( - self, tilingSchedule: TilingSchedule, nodeMemoryConstraint: NodeMemoryConstraint, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[List[CodeSnippet], List[CodeSnippet]]: - - exportLoadStep = tilingSchedule.outputLoadSchedule - egressDMATransferCalls, egressDMAWaitStatements = self._generateDMACode(nodeMemoryConstraint, ctxt, - operatorRepresentation, exportLoadStep, - "FromL1") - - return egressDMATransferCalls, egressDMAWaitStatements - - def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, - nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, - variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - tileIdxPtr = self._hoistTileIdxPtr(ctxt, operatorRepresentation) - - ingressDMATransferCalls, ingressDMAWaitStatements = self._generateIngressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - egressDMATransferCalls, egressDMAWaitStatements = self._generateEgressDMACode( - tilingSchedule, nodeMemoryConstraint, ctxt, operatorRepresentation) - - ctxt, ingressDMAUpdates = self._generateIngressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - ctxt, egressDMAUpdates = self._generateEgressPointerUpdates(nodeMemoryConstraint, tilingSchedule, ctxt, - operatorRepresentation) - - openLoopStatement = [ - CodeSnippet(self._openTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - closeLoopStatement = [ - CodeSnippet(self._closeTileLoopTemplate, { - "numTiles": operatorRepresentation["numTiles"], - "tileIdxPtr": tileIdxPtr - }) - ] - - variableUpdates = self._generateVariableUpdates(tilingSchedule, variableReplacement, ctxt, - operatorRepresentation) - - metaInfo = TilingMetaInfo(nodeName = operatorRepresentation['nodeName'] + "_L2", - nodeOps = operatorRepresentation['nodeOps'], - numTiles = len(tilingSchedule.outputLoadSchedule), - tileIdxVar = "TILING_I", - kernelLevelTiling = True) - - newExecutionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements, ingressDMAUpdates, - egressDMATransferCalls, egressDMAWaitStatements, - egressDMAUpdates, variableUpdates, openLoopStatement, - closeLoopStatement, [], []) - - return ctxt, newExecutionBlock, True - - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - # SCHEREMO: hoist numTiles - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == 1: - return ctxt, executionBlock, False - - operatorRepresentation["numTiles"] = self._hoistNumTiles(ctxt, operatorRepresentation['nodeName'], - tilingSchedules) - - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) - - -class SnitchClusterTilingGenerationSB(SnitchClusterTilingSB, SingleBufferingTilingMixIn): - pass diff --git a/Deeploy/Targets/Snitch/DMA/SnitchDma.py b/Deeploy/Targets/Snitch/DMA/SnitchDma.py new file mode 100644 index 0000000000..6e2533697d --- /dev/null +++ b/Deeploy/Targets/Snitch/DMA/SnitchDma.py @@ -0,0 +1,51 @@ +from typing import Dict, Tuple + +from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer +from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future, TensorGroupWaitingStrategy + + +class SnitchBarrierFuture(Future): + _initTemplate = NodeTemplate("") + _deinitTemplate = NodeTemplate("") + _waitTemplate = NodeTemplate("if (snrt_is_dm_core()) snrt_dma_wait_all();") + + +# LMACAN: TODO: Add single transfer waiting +class SnitchFuture(Future): + _initTemplate = NodeTemplate("uint16_t ${name};") + _deinitTemplate = NodeTemplate("") + _waitTemplate = NodeTemplate("if (snrt_is_dm_core()) snrt_dma_wait(${name});") + + +class SnitchDma(AsyncDma): + + _transferTemplates = { + 2: + NodeTemplate( + "if (snrt_is_dm_core()) snrt_dma_start_2d(${dest}, ${src}, ${size}, ${stride_dest}, ${stride_src}, ${repeat});" + ), + } + _waitingStrategy = TensorGroupWaitingStrategy(SnitchBarrierFuture, "") + + def __init__(self, transferTemplates: Dict[int, NodeTemplate] = _transferTemplates) -> None: + super().__init__(transferTemplates) + + def checkTransfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection) -> None: + super().checkTransfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction) + assert strideLoc[1] == 1 and strideExt[1] == 1, f"Supports only contigous transfers in the innermost dimension" + + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], + strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, + future: Future) -> OperatorRepresentation: + _ = future + operatorRepresentation: OperatorRepresentation = { + "dest": localBuffer.name if direction == "ExternalToLocal" else externalBuffer.name, + "src": externalBuffer.name if direction == "ExternalToLocal" else localBuffer.name, + "repeat": shape[0], + "size": shape[1], + "stride_dest": strideLoc[0] if direction == "ExternalToLocal" else strideExt[0], + "stride_src": strideExt[0] if direction == "ExternalToLocal" else strideLoc[0], + } + return operatorRepresentation diff --git a/Deeploy/TilingExtension/AsyncDma.py b/Deeploy/TilingExtension/AsyncDma.py new file mode 100644 index 0000000000..ea1dd99edf --- /dev/null +++ b/Deeploy/TilingExtension/AsyncDma.py @@ -0,0 +1,247 @@ +import math +from abc import ABC, abstractmethod +from typing import Dict, List, Literal, Set, Tuple, Type + +from Deeploy.DeeployTypes import CodeSnippet, NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer, \ + _ReferenceBuffer +from Deeploy.TilingExtension.TilingCodegen import padShape, padStride + +DmaDirection = Literal["ExternalToLocal", "LocalToExternal"] + + +class Future: + + _initTemplate: NodeTemplate + _deinitTemplate: NodeTemplate + _waitTemplate: NodeTemplate + + def __init__(self, name: str): + self.name = name + + def _operatorRepresentation(self) -> OperatorRepresentation: + return {"name": self.name} + + def init(self) -> CodeSnippet: + return CodeSnippet(self._initTemplate, self._operatorRepresentation()) + + def deinit(self) -> CodeSnippet: + return CodeSnippet(self._deinitTemplate, self._operatorRepresentation()) + + def wait(self) -> CodeSnippet: + return CodeSnippet(self._waitTemplate, self._operatorRepresentation()) + + +class AsyncDmaWaitingStrategy(ABC): + + def __init__(self, FutureCls: Type[Future]) -> None: + self.FutureCls = FutureCls + + @abstractmethod + def getFuture(self, tensorName: str) -> Future: + pass + + +class PerTensorWaitingStrategy(AsyncDmaWaitingStrategy): + + def getFuture(self, tensorName: str) -> Future: + return self.FutureCls(tensorName + "_future") + + +class TensorGroupWaitingStrategy(AsyncDmaWaitingStrategy): + + def __init__(self, FutureCls: Type[Future], asyncGroupName: str) -> None: + super().__init__(FutureCls) + self.asyncGroupFuture = FutureCls(f"{asyncGroupName}_future") + + def getFuture(self, tensorName: str) -> Future: + _ = tensorName + return self.asyncGroupFuture + + +class AsyncDma(ABC): + + _waitingStrategy: AsyncDmaWaitingStrategy + + def __init__(self, transferTemplates: Dict[int, NodeTemplate]) -> None: + self._transferTemplates = transferTemplates + + def getFuture(self, tensorName: str) -> Future: + return self._waitingStrategy.getFuture(tensorName) + + def supportedTransferRanks(self) -> Set[int]: + return set(self._transferTemplates.keys()) + + def checkTransfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection) -> None: + transferRank = len(shape) + assert transferRank == len(strideLoc) and transferRank == len( + strideExt), f"The shape and stride rank should match" + assert transferRank in self.supportedTransferRanks( + ), f"Unsupported transfer rank {transferRank}. Supported ranks are {self.supportedTransferRanks()}" + + @abstractmethod + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], + strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, + future: Future) -> OperatorRepresentation: + return {"loc": localBuffer.name, "ext": externalBuffer.name, "future": future.name} + + def transfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection, future: Future) -> List[CodeSnippet]: + self.checkTransfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction) + opRepr = self.transferOpRepr(externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, future) + template = self._transferTemplates[len(shape)] + return [CodeSnippet(template, opRepr)] + + def setup(self) -> List[CodeSnippet]: + return [] + + def teardown(self) -> List[CodeSnippet]: + return [] + + +class EmptyFuture(Future): + + _initTemplate = NodeTemplate("") + _deinitTemplate = NodeTemplate("") + _waitTemplate = NodeTemplate("") + + +class BlockingDmaFromAsyncDmaAdapter(AsyncDma): + + _waitingStrategy = PerTensorWaitingStrategy(EmptyFuture) + + def __init__(self, dma: AsyncDma) -> None: + self.dma = dma + + @property + def _transferTemplates(self) -> Dict[int, NodeTemplate]: + return self.dma._transferTemplates + + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], + strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, + future: Future) -> OperatorRepresentation: + return self.dma.transferOpRepr(externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, future) + + def transfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, + shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], + direction: DmaDirection, future: Future) -> List[CodeSnippet]: + tmpFuture = self.dma.getFuture(future.name.removesuffix("_future")) + callStack = [] + callStack.append(tmpFuture.init()) + callStack.extend( + self.dma.transfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, tmpFuture)) + callStack.append(tmpFuture.wait()) + callStack.append(tmpFuture.deinit()) + return callStack + + def setup(self) -> List[CodeSnippet]: + return self.dma.setup() + + def teardown(self) -> List[CodeSnippet]: + return self.dma.teardown() + + +class AnydimAsyncDmaTransferAdapter: + + class NestedForLoopOpenTemplate(NodeTemplate): + + def __init__(self, depth: int): + templateStr = "" + for level in range(depth): + iter = f"i_{level}" + templateStr += f"for (uint32_t {iter} = 0; {iter} < ${{end_{level}}}; {iter}++) {{" + super().__init__(templateStr) + + class NestedForLoopCloseTemplate(NodeTemplate): + + def __init__(self, depth: int): + templateStr = "" + for _ in range(depth): + templateStr += "}" + super().__init__(templateStr) + + class OffsetCalculationTemplate(NodeTemplate): + + def __init__(self, name: str, depth: int): + templateStr = f"const uint32_t {name} = " + for i in range(depth): + templateStr += f"i_{i} * ${{stride_{i}}}" + if i < depth - 1: + templateStr += " + " + templateStr += ";" + super().__init__(templateStr) + + offsetPtrTemplate = NodeTemplate("void * const ${resultPtr} = (void *)${basePtr} + ${offset};") + + def __init__(self, dma: AsyncDma) -> None: + self.dma = dma + + def nearestSupportedTransferRank(self, transfer_rank: int) -> int: + sortedRanks = sorted(self.dma.supportedTransferRanks()) + + # Find nearest smaller + for rank in reversed(sortedRanks): + if rank <= transfer_rank: + return rank + + # All supported ranks are bigger so return the smallest one + return sortedRanks[0] + + def transfer(self, + ctxt: NetworkContext, + externalBuffer: VariableBuffer, + localBuffer: VariableBuffer, + shape: Tuple[int, ...], + strideExt: Tuple[int, ...], + strideLoc: Tuple[int, ...], + direction: DmaDirection, + future: Future, + strideExtPad: int = 0) -> List[CodeSnippet]: + transferRank = len(shape) + kernelRank = self.nearestSupportedTransferRank(transferRank) + + if kernelRank < transferRank: + nestedLoopDepth = transferRank - kernelRank + + nestedLoopOpRepr = {f"end_{level}": shape[level] for level in range(nestedLoopDepth)} + locOffsetCalculationOpRepr = {f"stride_{level}": strideLoc[level] for level in range(nestedLoopDepth)} + extOffsetCalculationOpRepr = {f"stride_{level}": strideExt[level] for level in range(nestedLoopDepth)} + + callStack = [] + callStack.append(CodeSnippet(self.NestedForLoopOpenTemplate(nestedLoopDepth), nestedLoopOpRepr)) + callStack.append( + CodeSnippet(self.OffsetCalculationTemplate("ext_offset", nestedLoopDepth), extOffsetCalculationOpRepr)) + callStack.append( + CodeSnippet(self.OffsetCalculationTemplate("loc_offset", nestedLoopDepth), locOffsetCalculationOpRepr)) + + localBufferOffseted = _ReferenceBuffer("local_buffer_offsetted", localBuffer) + localBufferOffseted._memoryLevel = localBuffer._memoryLevel + callStack.append( + CodeSnippet(self.offsetPtrTemplate, { + "resultPtr": "local_buffer_offsetted", + "basePtr": localBuffer.name, + "offset": "loc_offset" + })) + + externalBufferOffseted = _ReferenceBuffer("external_buffer_offsetted", externalBuffer) + externalBufferOffseted._memoryLevel = externalBuffer._memoryLevel + callStack.append( + CodeSnippet(self.offsetPtrTemplate, { + "resultPtr": externalBufferOffseted.name, + "basePtr": externalBuffer.name, + "offset": "ext_offset" + })) + + callStack.extend( + self.dma.transfer(ctxt, externalBufferOffseted, localBufferOffseted, shape[-kernelRank:], + strideExt[-kernelRank:], strideLoc[-kernelRank:], direction, future)) + callStack.append(CodeSnippet(self.NestedForLoopCloseTemplate(nestedLoopDepth), {})) + return callStack + elif kernelRank == transferRank: + return self.dma.transfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, future) + else: + return self.dma.transfer(ctxt, externalBuffer, localBuffer, padShape(shape, kernelRank), + padStride(strideExt, kernelRank, strideExtPad), + padStride(strideLoc, kernelRank, math.prod(shape)), direction, future) diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py new file mode 100644 index 0000000000..dc7a790604 --- /dev/null +++ b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py @@ -0,0 +1,249 @@ +# ---------------------------------------------------------------------- +# +# File: PULPClusterTilingDB.py +# +# Last edited: 25.10.2023 +# +# Copyright (C) 2023, ETH Zurich and University of Bologna. +# +# Author: Moritz Scherer, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import math +from typing import List, Set, Tuple + +from Deeploy.AbstractDataTypes import VoidType +from Deeploy.DeeployTypes import CodeSnippet, ExecutionBlock, NetworkContext, NodeTemplate, OperatorRepresentation, \ + VariableBuffer, _ReferenceBuffer +from Deeploy.TilingExtension.AsyncDma import AnydimAsyncDmaTransferAdapter, AsyncDma, Future +from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import dictOfArrays +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import TilingMetaInfo +from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint +from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme, stridesFromShape + + +class DoubleBufferingTilingCodeGeneration(TilingCodeGeneration): + + _moveTileInCheckOpenStatement = NodeTemplate(""" + // DOUBLE BUFFERING CHECK TILE LOAD + if ((${tileIdxVar}) < ${numTiles}[*${tileIdxPtr}+1]) { + """) + + _moveTileInCheckCloseStatement = NodeTemplate(""" + } + """) + + # LMACAN: The brackets around ${tileIdxVar} are important to ensure correct order + # of the modulo operation. Breaking case without the brackets is when we + # put "TILING_I + 1" for tileIdxVar. + _chooseBufferTemplate = NodeTemplate(""" + switch((${tileIdxVar}) % 2) { + case 0: ${reference} = (${type})${buffer_0}; break; + case 1: ${reference} = (${type})${buffer_1}; break; + } + """) + + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): + super().__init__(externalMemory, localMemory, dma, 2) + + def _generateBufferChoice(self, reference: VariableBuffer, buffers: List[_ReferenceBuffer], + tileIdxVar: str) -> CodeSnippet: + assert len(buffers) == 2, f"Only double buffering supported. Received {len(buffers)} buffers." + operatorRepresentation = { + "tileIdxVar": tileIdxVar, + "reference": reference.name, + "type": reference._type.typeName, + "buffer_0": buffers[0].name, + "buffer_1": buffers[1].name, + } + template = self._chooseBufferTemplate + return CodeSnippet(template, operatorRepresentation) + + def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, + nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, + variableReplacement: VariableReplacementScheme, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: + + setupStatements: List[CodeSnippet] = [] + teardownStatements: List[CodeSnippet] = [] + + openLoopStatements: List[CodeSnippet] = [CodeSnippet(self._openTileLoopTemplate, {**operatorRepresentation})] + + ingressDmaTransferCalls: List[CodeSnippet] = [ + CodeSnippet(self._moveTileInCheckOpenStatement, { + **operatorRepresentation, "tileIdxVar": "TILING_I+1" + }) + ] + + ingressFutures: Set[Future] = set() + initialFutures: Set[Future] = set() + + for tensorName, rectangles in dictOfArrays(tilingSchedule.inputLoadSchedule).items(): + localBuffer = ctxt.lookup(operatorRepresentation[tensorName]) + assert localBuffer._memoryLevel == self.localMemory + assert isinstance(localBuffer, _ReferenceBuffer) + externalBuffer = ctxt.lookup(localBuffer._referenceName) + assert isinstance(externalBuffer, VariableBuffer) + tensorMemoryConstraint = nodeMemoryConstraint.inputTensorMemoryConstraints[externalBuffer.name] + externalBufferShape = tensorMemoryConstraint.memoryConstraints[self.externalMemory].shape + assert externalBufferShape is not None + + rectangles, externalBufferShape = self._legalizeTransfers(rectangles, tuple(externalBufferShape), + localBuffer._type.referencedType.typeWidth, + self.isFinalMemoryLevel(tensorMemoryConstraint)) + + externalBufferRef = self._hoistReference(ctxt, + externalBuffer.name + "_ref", + externalBuffer, + externalBufferShape, + override_type = VoidType) + + tensorMemoryConstraint = nodeMemoryConstraint.inputTensorMemoryConstraints[externalBuffer.name] + l1BuffersReferences = self._hoistMultibufferReferences(ctxt, localBuffer, tensorMemoryConstraint) + + nextLocalBufferReference = self._hoistReference(ctxt, f"{tensorName}_next", l1BuffersReferences[1]) + + openLoopStatements.append(self._generateBufferChoice(localBuffer, l1BuffersReferences, "TILING_I")) + + future = self.dma.getFuture(tensorName) + ingressFutures.add(future) + + ingressDmaTransferCalls.append( + self._generateBufferChoice(nextLocalBufferReference, l1BuffersReferences, "TILING_I+1")) + ingressDmaTransferCalls.extend( + self._generateDmaTransferCalls(ctxt, tensorName, rectangles, "TILING_I+1", nextLocalBufferReference, + externalBufferRef, "ExternalToLocal", future)) + + anydimAdapter = AnydimAsyncDmaTransferAdapter(self.dma) + + initialFuture = self.dma.getFuture(tensorName + "_init") + initialFutures.add(initialFuture) + initialDmaTransferCalls = anydimAdapter.transfer(ctxt, externalBufferRef, localBuffer, rectangles[0].dims, + stridesFromShape(externalBufferShape), + stridesFromShape(rectangles[0].dims), "ExternalToLocal", + initialFuture, math.prod(externalBufferShape)) + setupStatements.extend(initialDmaTransferCalls) + setupStatements.append(initialFuture.wait()) + + referenceUpdate = self._generateExternalReferenceUpdate(ctxt, tensorName, rectangles, "TILING_I+1", + externalBufferRef) + if referenceUpdate is not None: + ingressDmaTransferCalls.append(referenceUpdate) + initialReferenceUpdate = CodeSnippet(referenceUpdate.template, + operatorRepresentation = { + **referenceUpdate.operatorRepresentation, + "tileIdxVar": 0, + }) + setupStatements.append(initialReferenceUpdate) + + ingressDmaTransferCalls.append(CodeSnippet(self._moveTileInCheckCloseStatement, {})) + ingressDmaWaitStatements = [f.wait() for f in ingressFutures] + + egressDmaTransferCalls: List[CodeSnippet] = [] + egressFutures: Set[Future] = set() + + for tensorName, rectangles in dictOfArrays(tilingSchedule.outputLoadSchedule).items(): + localBuffer = ctxt.lookup(operatorRepresentation[tensorName]) + assert localBuffer._memoryLevel == self.localMemory + assert isinstance(localBuffer, _ReferenceBuffer) + externalBuffer = ctxt.lookup(localBuffer._referenceName) + assert isinstance(externalBuffer, VariableBuffer) + tensorMemoryConstraint = nodeMemoryConstraint.outputTensorMemoryConstraints[externalBuffer.name] + externalBufferShape = tensorMemoryConstraint.memoryConstraints[self.externalMemory].shape + assert externalBufferShape is not None + + rectangles, externalBufferShape = self._legalizeTransfers(rectangles, tuple(externalBufferShape), + localBuffer._type.referencedType.typeWidth, + self.isFinalMemoryLevel(tensorMemoryConstraint)) + + externalBufferRef = self._hoistReference(ctxt, + externalBuffer.name + "_ref", + externalBuffer, + externalBufferShape, + override_type = VoidType) + + tensorMemoryConstraint = nodeMemoryConstraint.outputTensorMemoryConstraints[externalBuffer.name] + l1BuffersReferences = self._hoistMultibufferReferences(ctxt, localBuffer, tensorMemoryConstraint) + + openLoopStatements.append(self._generateBufferChoice(localBuffer, l1BuffersReferences, "TILING_I")) + + future = self.dma.getFuture(tensorName) + egressFutures.add(future) + + dmaTransferCalls = self._generateDmaTransferCalls(ctxt, tensorName, rectangles, "TILING_I", localBuffer, + externalBufferRef, "LocalToExternal", future) + egressDmaTransferCalls.extend(dmaTransferCalls) + + referenceUpdate = self._generateExternalReferenceUpdate(ctxt, tensorName, rectangles, "TILING_I", + externalBufferRef) + if referenceUpdate is not None: + egressDmaTransferCalls.append(referenceUpdate) + + egressDmaWaitStatements = [f.wait() for f in egressFutures] + + teardownStatements.extend([f.wait() for f in egressFutures]) + + setupStatements = [f.init() for f in ingressFutures | initialFutures | egressFutures] + setupStatements + teardownStatements.extend(f.deinit() for f in ingressFutures | initialFutures | egressFutures) + + closeLoopStatements = [CodeSnippet(self._closeTileLoopTemplate, {**operatorRepresentation})] + + metaInfo = TilingMetaInfo( + nodeName = operatorRepresentation['nodeName'] + f"_{self.externalMemory}", + nodeOps = operatorRepresentation['nodeOps'], + numTiles = operatorRepresentation['numTiles'], + totalNumTiles = len(tilingSchedule.outputLoadSchedule), + tileIdxPtr = operatorRepresentation['tileIdxPtr'], + tileIdxVar = "TILING_I", + # TODO: The kernelLevelTiling field is used in profiling to know we are generating code around the kernel. + # The current implementation does this by checking whether we are at the lowest memory level, + # which is hardcoded by the value "L1". Change this to be memory level agnostic. + kernelLevelTiling = self.localMemory == "L1") + + executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDmaTransferCalls, + ingressDmaWaitStatements, [], egressDmaTransferCalls, + egressDmaWaitStatements, [], [], openLoopStatements, + closeLoopStatements, setupStatements, teardownStatements) + + return ctxt, executionBlock, True + + def generateTilingLoop( + self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, + tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: + + flatTilingSchedule = copy.copy(tilingSchedules[0]) + for tilingSchedule in tilingSchedules[1:]: + flatTilingSchedule += tilingSchedule + + offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) + + if len(offsetLists) == 0: + return ctxt, executionBlock, False + + for offsetList in offsetLists: + if not len(offsetList) == self.bufferCount: + return ctxt, executionBlock, False + + numTiles, tileIdxPtr = self._hoistTileNumAndIdxPtr(ctxt, tilingSchedules) + operatorRepresentation["numTiles"] = numTiles.name + operatorRepresentation["tileIdxPtr"] = tileIdxPtr.name + + return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, + operatorRepresentation) diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py new file mode 100644 index 0000000000..52c8568efc --- /dev/null +++ b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py @@ -0,0 +1,153 @@ +# ---------------------------------------------------------------------- +# +# File: PULPL3TilingSB.py +# +# Last edited: 19.04.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: Moritz Scherer, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +from typing import Dict, List, Set, Tuple + +from Deeploy.AbstractDataTypes import VoidType +from Deeploy.DeeployTypes import CodeSnippet, ExecutionBlock, NetworkContext, OperatorRepresentation, VariableBuffer, \ + _ReferenceBuffer +from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future +from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration +from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import dictOfArrays +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import TilingMetaInfo +from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint, TensorMemoryConstraint +from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme + + +class SingleBufferingTilingCodeGeneration(TilingCodeGeneration): + + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): + super().__init__(externalMemory, localMemory, dma, 1) + + def _generateTransferScheduleCalls( + self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, + transferSchedule: List[Dict[str, HyperRectangle]], tensorMemoryConstraintDict: Dict[str, + TensorMemoryConstraint], + tileIdxVar: str, direction: DmaDirection) -> Tuple[NetworkContext, List[CodeSnippet], Set[Future]]: + callStack: List[CodeSnippet] = [] + referenceUpdates: List[CodeSnippet] = [] + futures: Set[Future] = set() + + for tensorName, rectangles in dictOfArrays(transferSchedule).items(): + localBuffer = ctxt.lookup(operatorRepresentation[tensorName]) + assert localBuffer._memoryLevel == self.localMemory + assert isinstance(localBuffer, _ReferenceBuffer) + externalBuffer = ctxt.lookup(localBuffer._referenceName) + assert isinstance(externalBuffer, VariableBuffer) + tensorMemoryConstraint = tensorMemoryConstraintDict[externalBuffer.name] + externalBufferShape = tensorMemoryConstraint.memoryConstraints[self.externalMemory].shape + assert externalBufferShape is not None + + rectangles, externalBufferShape = self._legalizeTransfers(rectangles, tuple(externalBufferShape), + localBuffer._type.referencedType.typeWidth, + self.isFinalMemoryLevel(tensorMemoryConstraint)) + + externalBufferRef = self._hoistReference(ctxt, + externalBuffer.name + "_ref", + externalBuffer, + shape = externalBufferShape, + override_type = VoidType) + + future = self.dma.getFuture(tensorName) + futures.add(future) + + callStack.extend( + self._generateDmaTransferCalls(ctxt, tensorName, rectangles, tileIdxVar, localBuffer, externalBufferRef, + direction, future)) + + referenceUpdate = self._generateExternalReferenceUpdate(ctxt, tensorName, rectangles, tileIdxVar, + externalBufferRef) + if referenceUpdate is not None: + callStack.append(referenceUpdate) + + return ctxt, callStack, futures + + def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, + nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, + variableReplacement: VariableReplacementScheme, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: + ctxt, ingressDmaTransferCalls, ingressFutures = self._generateTransferScheduleCalls( + ctxt, operatorRepresentation, tilingSchedule.inputLoadSchedule, + nodeMemoryConstraint.inputTensorMemoryConstraints, "TILING_I", "ExternalToLocal") + ctxt, egressDmaTransferCalls, egressFutures = self._generateTransferScheduleCalls( + ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, + nodeMemoryConstraint.outputTensorMemoryConstraints, "TILING_I", "LocalToExternal") + + ingressDmaWaitStatements = [future.wait() for future in ingressFutures] + egressDmaWaitStatements = [future.wait() for future in egressFutures] + + setupStatements = self.dma.setup() + setupStatements += [f.init() for f in ingressFutures | egressFutures] + + teardownStatements = self.dma.teardown() + teardownStatements.extend(f.deinit() for f in ingressFutures | egressFutures) + + openLoopStatements = [CodeSnippet(self._openTileLoopTemplate, {**operatorRepresentation})] + closeLoopStatements = [CodeSnippet(self._closeTileLoopTemplate, {**operatorRepresentation})] + + metaInfo = TilingMetaInfo( + nodeName = operatorRepresentation['nodeName'] + f"_{self.externalMemory}", + nodeOps = operatorRepresentation['nodeOps'], + numTiles = operatorRepresentation['numTiles'], + totalNumTiles = len(tilingSchedule.outputLoadSchedule), + tileIdxPtr = operatorRepresentation['tileIdxPtr'], + tileIdxVar = "TILING_I", + # TODO: The kernelLevelTiling field is used in profiling to know we are generating code around the kernel. + # The current implementation does this by checking whether we are at the lowest memory level, + # which is hardcoded by the value "L1". Change this to be memory level agnostic. + kernelLevelTiling = self.localMemory == "L1") + + executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDmaTransferCalls, + ingressDmaWaitStatements, [], egressDmaTransferCalls, + egressDmaWaitStatements, [], [], openLoopStatements, + closeLoopStatements, setupStatements, teardownStatements) + + return ctxt, executionBlock, True + + def generateTilingLoop( + self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, + tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: + + flatTilingSchedule = copy.copy(tilingSchedules[0]) + for tilingSchedule in tilingSchedules[1:]: + flatTilingSchedule += tilingSchedule + + offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) + + if len(offsetLists) == 0: + return ctxt, executionBlock, False + + for offsetList in offsetLists: + if not len(offsetList) == self.bufferCount: + return ctxt, executionBlock, False + + numTiles, tileIdxPtr = self._hoistTileNumAndIdxPtr(ctxt, tilingSchedules) + operatorRepresentation["numTiles"] = numTiles.name + operatorRepresentation["tileIdxPtr"] = tileIdxPtr.name + + return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, + operatorRepresentation) diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py index f4e4d9aae9..db5a1a3fce 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py @@ -23,150 +23,210 @@ # See the License for the specific language governing permissions and # limitations under the License. +import copy +import math from abc import abstractmethod -from typing import Dict, List, Optional, Tuple, Type +from typing import List, Optional, Tuple, TypeVar + +import numpy as np -import Deeploy.CommonExtensions.DataTypes as BasicDataTypes -from Deeploy.AbstractDataTypes import Immediate, PointerClass from Deeploy.CommonExtensions.CodeTransformationPasses.Closure import ClosureExecutionBlock from Deeploy.CommonExtensions.CodeTransformationPasses.IntrospectiveCodeTransformation import \ IntrospectiveCodeTransformationMixIn from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration -from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ConstantBuffer, ExecutionBlock, \ +from Deeploy.DeeployTypes import CodeGenVerbosity, CodeSnippet, CodeTransformationPass, ExecutionBlock, \ NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer, _NoVerbosity +from Deeploy.TilingExtension.AsyncDma import AnydimAsyncDmaTransferAdapter, AsyncDma, DmaDirection, Future +from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import TilingHoistingMixIn from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import PrototypeTilingMixIn -from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint -from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme, minimizeVariableReplacement +from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint, TensorMemoryConstraint +from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme, \ + calculateFlatOffset, minimizeRectangle, minimizeVariableReplacement, padOffset, padShape, stridesFromShape +T = TypeVar('T') -class TilingCodeGeneration(CodeTransformationPass, IntrospectiveCodeTransformationMixIn, PrototypeTilingMixIn): - def __init__(self, targetMemLevel: str): - self.targetMemLevel = targetMemLevel - self.argStructGeneration = ArgumentStructGeneration() +def transposeListOfLists(listOfLists: List[List[T]]) -> List[List[T]]: + transposedListOfLists = [] + for _list in listOfLists: + for i, element in enumerate(_list): + if i >= len(transposedListOfLists): + assert i == len(transposedListOfLists) + transposedListOfLists.append([element]) + else: + transposedListOfLists[i].append(element) + return transposedListOfLists + + +class TilingCodeGeneration(CodeTransformationPass, IntrospectiveCodeTransformationMixIn, PrototypeTilingMixIn, + TilingHoistingMixIn): + + _relativeOffsetReferenceUpdateTemplate = NodeTemplate(""" + // UPDATE VARIABLE ${reference} + ${reference} += ${relativeOffset}; + """) + + _relativeOffsetReferenceUpdateTiledTemplate = NodeTemplate(""" + // UPDATE VARIABLE ${reference} + ${reference} += ${relativeOffset}[${tileIdxVar}]; + """) + + _openTileLoopTemplate = NodeTemplate(""" + // TILING LOOP + for (int TILING_I=${numTiles}[*${tileIdxPtr}]; TILING_I<${numTiles}[(*${tileIdxPtr})+1]; TILING_I++){ + """) + + _closeTileLoopTemplate = NodeTemplate(""" + // CLOSE TILING LOOP + } + *${tileIdxPtr} += 1; + """) @abstractmethod def generateTilingLoop( self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, + tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: return ctxt, executionBlock, False + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma, bufferCount: int): + self.externalMemory = externalMemory + self.localMemory = localMemory + self.dma = dma + self.bufferCount = bufferCount + TilingHoistingMixIn.__init__(self, localMemory) + self.argStructGeneration = ArgumentStructGeneration() + # SCHEREMO: internalPtr refers to the HIGHER memory level of a transfer, # e.g. in both an L2 -> L1 and L1 -> L2 transfer, the internalPtr is in L1. - @staticmethod - def isFinalMemoryLevel(nodeMemoryConstraint: NodeMemoryConstraint, internalPtr: VariableBuffer) -> bool: - externalName = internalPtr._referenceName - tensorMemoryConstraint = nodeMemoryConstraint.tensorMemoryConstraints[externalName] - if len(tensorMemoryConstraint.memoryConstraints.keys()) <= 2: + def isFinalMemoryLevel(self, tensorMemoryConstraint: TensorMemoryConstraint) -> bool: + memoryOrder = list(tensorMemoryConstraint.memoryConstraints.keys()) + assert self.localMemory in memoryOrder, f"Memory {self.localMemory} does not exist in the tensor memory constraint {tensorMemoryConstraint}" + if len(memoryOrder) < 2: return True + return self.localMemory in memoryOrder[:2] - finalMemoryLevels = list(tensorMemoryConstraint.memoryConstraints.keys())[:2] - memoryLevel = internalPtr._memoryLevel + def _generateDmaTransferCalls(self, ctxt: NetworkContext, tensorName: str, transfers: List[HyperRectangle], + tileIdxVar: str, localBuffer: VariableBuffer, externalBuffer: VariableBuffer, + direction: DmaDirection, future: Future) -> List[CodeSnippet]: + assert all(len(transfers[0].dims) == len(rect.dims) for rect in transfers), \ + "Currently supporting only rectangles of same rank" - return memoryLevel in finalMemoryLevels + assert len(transfers[0].dims) > 0, "Expecting transfers of rank greater than 0" - def _hoistTileIdxPtr(self, - ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation, - sourceMemoryLevel: str = "L2") -> str: + assert len(transfers[0].dims) == len(externalBuffer.shape), \ + "External buffer's rank should be equal to the internal buffer's" - newPtrName = self.prefix + operatorRepresentation['nodeName'] + "_tileIdxPtr" + anydimAdapter = AnydimAsyncDmaTransferAdapter(self.dma) - tilePtrBuffer = ctxt.VariableBuffer(newPtrName, shape = [1]) - ctxt.add(tilePtrBuffer, "local") + initSnippets = anydimAdapter.transfer(ctxt, externalBuffer, localBuffer, transfers[0].dims, + stridesFromShape(externalBuffer.shape), + stridesFromShape(transfers[0].dims), direction, future, + math.prod(externalBuffer.shape)) - _type = ctxt.lookup(self.prefix + operatorRepresentation['nodeName'] + "_numTiles")._type + templates = [snippet.template for snippet in initSnippets] + opReprUpdates = [[] for _ in range(len(initSnippets))] - tilePtrBuffer._type = _type - tilePtrBuffer._instance = tilePtrBuffer._type(newPtrName, ctxt) - tilePtrBuffer._memoryLevel = sourceMemoryLevel + for rect in transfers: + snippets = anydimAdapter.transfer(ctxt, externalBuffer, localBuffer, rect.dims, + stridesFromShape(externalBuffer.shape), stridesFromShape(rect.dims), + direction, future, math.prod(externalBuffer.shape)) + for i, snippet in enumerate(snippets): + opReprUpdates[i].append(snippet.operatorRepresentation) - tilePtrBuffer.allocTemplate = NodeTemplate("") - tilePtrBuffer.deallocTemplate = NodeTemplate("") - tilePtrBuffer.initTemplate = NodeTemplate(""" - ${type.referencedType.typeName} bu_${name} = 0; - ${type.referencedType.typeName}* ${name} = &bu_${name};""") - - return newPtrName + tiledSnippets: List[CodeSnippet] = [ + CodeSnippet(*self._tileTemplate(ctxt, opReprUpdate, template, tileIdxVar, f"{tensorName}_")) + for template, opReprUpdate in zip(templates, opReprUpdates) + ] - def _hoistNumTiles(self, - ctxt: NetworkContext, - nodeName: str, - tilingSchedules: List[TilingSchedule], - sourceMemoryLevel: str = "L2") -> str: + return tiledSnippets - newPtrName = self.prefix + nodeName + "_numTiles" + def _generateExternalReferenceUpdate(self, ctxt: NetworkContext, tensorName: str, transfers: List[HyperRectangle], + tileIdxVar: str, externalBuffer: VariableBuffer) -> Optional[CodeSnippet]: + externalBufferStrides = stridesFromShape(externalBuffer.shape) + offsets = [calculateFlatOffset(rect.offset, externalBufferStrides) for rect in transfers] + relativeOffsets = [_next - _prev for _prev, _next in zip(offsets[:-1], offsets[1:])] - numTiles = [len(tilingSchedule.outputLoadSchedule) for tilingSchedule in tilingSchedules] - cumNumTiles = [0] - for idx in list(range(len(numTiles))): - cumNumTiles.append(cumNumTiles[-1] + numTiles[idx]) + if len(relativeOffsets) == 0 or all(offset == 0 for offset in relativeOffsets): + return None - cb = ctxt.ConstantBuffer(newPtrName, [len(cumNumTiles)], values = cumNumTiles) - ctxt.add(cb, "global") + operatorRepresentation: OperatorRepresentation = {"reference": externalBuffer.name, "tileIdxVar": tileIdxVar} - minType = None - if BasicDataTypes.uint8_t.checkValue(cumNumTiles): - minType = BasicDataTypes.uint8_t - elif BasicDataTypes.uint16_t.checkValue(cumNumTiles): - minType = BasicDataTypes.uint16_t + if all(relativeOffsets[0] == offset for offset in relativeOffsets): + operatorRepresentation["relativeOffset"] = relativeOffsets[0] + template = self._relativeOffsetReferenceUpdateTemplate else: - minType = BasicDataTypes.uint32_t - - cb._type = PointerClass(minType) - cb._instance = cb._type(newPtrName, ctxt) - cb._memoryLevel = sourceMemoryLevel - - return newPtrName - - def _hoistConstantAndReference(self, - ctxt: NetworkContext, - constBuf: ConstantBuffer, - operatorRepresentation: OperatorRepresentation, - nodeName: str, - operatorRepresentationName: str, - immediateType: Optional[Type[Immediate]] = None) -> Tuple[NetworkContext, Dict]: - - if immediateType is None: - _type = PointerClass(BasicDataTypes.int32_t) + relativeOffsets.append(0) # To have the same length as the number of tiles + buffer = self._hoistValues(ctxt, f'{tensorName}_relativeOffset', relativeOffsets) + operatorRepresentation["relativeOffset"] = buffer.name + operatorRepresentation["tileIdxVar"] = tileIdxVar + template = self._relativeOffsetReferenceUpdateTiledTemplate + + return CodeSnippet(template, operatorRepresentation) + + # TODO: Not super sure this should go here. It could be shared, but it seems a little bit too specific + # with the `isFinalMemory` thing. + def _legalizeTransfers(self, transfers: List[HyperRectangle], outerShape: Tuple[int, ...], typeWidth: int, + isFinalMemoryLevel: bool) -> Tuple[List[HyperRectangle], Tuple[int, ...]]: + transfersCommonRank = max(len(rect.dims) for rect in transfers) + commonRank = max(transfersCommonRank, len(outerShape)) + outerShape = padShape(outerShape, commonRank) + + minOuterShape = None + + if isFinalMemoryLevel: + minimizedTransfers = [] + for rect in transfers: + paddedRect = HyperRectangle(padOffset(rect.offset, commonRank), padShape(rect.dims, commonRank)) + minRect, newMinOuterShape = minimizeRectangle(paddedRect, outerShape) + if minOuterShape is None: + minOuterShape = newMinOuterShape + else: + if minOuterShape != newMinOuterShape: + rectStr = "\n".join(str(trans) for trans in transfers[:transfers.index(rect)]) + raise RuntimeError(f"""Currently support a single minimal outer shape. +Old minOuterShape: {minOuterShape} vs. new minOuterShape {newMinOuterShape}. +New minOuterShape produced by outerDims: {outerShape} and rect: {rect}. +Old minOuterShape produced by outerDims: {outerShape} and rects: +{rectStr}""") + minimizedTransfers.append(minRect) else: - _type = PointerClass(immediateType) + minimizedTransfers = [HyperRectangle((0,), (int(np.prod(rect.dims)),)) for rect in transfers] + minOuterShape = (int(np.prod(outerShape)),) + + if minOuterShape is not None: + outerShape = minOuterShape + transfers = minimizedTransfers - name = constBuf.name + def sizeInBytes(length: int, typeWidth: int) -> int: + return int(np.ceil((length * typeWidth) / 8)) - ctxt.add(constBuf, "global") - constBuf._type = _type - constBuf._instance = constBuf._type(name, ctxt) - constBuf._users = [nodeName] - constBuf._memoryLevel = self.targetMemLevel + outerShape = outerShape[:-1] + (sizeInBytes(outerShape[-1], typeWidth),) - refName = name + "_ref" - reference = ctxt.hoistReference(name, refName) - ctxt.lookup(reference)._memoryLevel = self.targetMemLevel + inBytesTransfers = [] + for rect in transfers: + newOffset = rect.offset[:-1] + (sizeInBytes(rect.offset[-1], typeWidth),) + newDims = rect.dims[:-1] + (sizeInBytes(rect.dims[-1], typeWidth),) + inBytesTransfers.append(HyperRectangle(newOffset, newDims)) + transfers = inBytesTransfers - operatorRepresentation[operatorRepresentationName] = refName + return transfers, outerShape - return ctxt, operatorRepresentation + def _tileTemplate(self, ctxt: NetworkContext, perTileOpReprs: List[OperatorRepresentation], template: NodeTemplate, + tileIdxVar: str, prefix: str) -> Tuple[NodeTemplate, OperatorRepresentation]: + opRepr, hoistedNames = self._hoistOpReprUpdates(ctxt, perTileOpReprs, prefix) + if len(hoistedNames) > 0: + template = copy.deepcopy(template) + self.indexVars(template.template, hoistedNames, "tileIdxVar") + opRepr["tileIdxVar"] = tileIdxVar + return template, opRepr def apply(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: - - def unravelReference(ctxt: NetworkContext, name: str) -> str: - - if name not in ctxt.localObjects.keys() and name not in ctxt.globalObjects.keys(): - return name - - refBuffer = ctxt.lookup(name) - if not hasattr(refBuffer, "_referenceName"): - return name - - return unravelReference(ctxt, refBuffer._referenceName) - if isinstance(executionBlock, ClosureExecutionBlock): baseExecutionBlock = executionBlock.baseBlock else: @@ -190,25 +250,24 @@ def unravelReference(ctxt: NetworkContext, name: str) -> str: templateNode = possibleTemplateNodes[0] - operatorRepresentation = templateNode.operatorRepresentation - unravelRep = operatorRepresentation.copy() - for key in unravelRep.keys(): - - val = unravelRep[key] - if not isinstance(val, str): - continue - - unravelRep[key] = unravelReference(ctxt, val) + self._initPrefix(templateNode.operatorRepresentation['nodeName']) + operatorRepresentation = templateNode.operatorRepresentation template = templateNode.template + unraveledOpRepr = operatorRepresentation.copy() + for key, value in unraveledOpRepr.items(): + if ctxt.is_buffer(value): + buffer = ctxt.lookup(value) + assert isinstance(buffer, VariableBuffer) + unraveledOpRepr[key] = ctxt.unravelReference(buffer).name + variableReplacement, tilingSchedules = template.tileConstraint.wrapTilingSolution( - nodeMemoryConstraint, self.targetMemLevel, ctxt, unravelRep) + nodeMemoryConstraint, self.localMemory, ctxt, unraveledOpRepr) + + minimalVariableReplacement, newOpRepr = minimizeVariableReplacement(variableReplacement, operatorRepresentation) - minimalVariableReplacement, newNodeRep = minimizeVariableReplacement(variableReplacement, - templateNode.operatorRepresentation) - for key, value in newNodeRep.items(): - templateNode.operatorRepresentation[key] = value + operatorRepresentation.update(newOpRepr) ctxt, executionBlock, applicable = self.generateTilingLoop(ctxt, executionBlock, nodeMemoryConstraint, tilingSchedules, minimalVariableReplacement, @@ -216,4 +275,6 @@ def unravelReference(ctxt: NetworkContext, name: str) -> str: if applicable: ctxt, executionBlock = self.argStructGeneration.apply(ctxt, executionBlock, name) + self._deinitPrefix() + return ctxt, executionBlock diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py new file mode 100644 index 0000000000..4aa0f03de9 --- /dev/null +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py @@ -0,0 +1,149 @@ +import math +from typing import List, Mapping, Optional, Sequence, Tuple, Type, TypeVar, Union + +import Deeploy.CommonExtensions.DataTypes as BasicDataTypes +from Deeploy.AbstractDataTypes import BaseType, PointerClass, VoidType +from Deeploy.DeeployTypes import ConstantBuffer, NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer, \ + _ReferenceBuffer +from Deeploy.TilingExtension.MemoryConstraints import TensorMemoryConstraint +from Deeploy.TilingExtension.TilingCodegen import TilingSchedule + +KT = TypeVar('KT') +VT = TypeVar('VT') + + +def dictOfArrays(arrayOfDicts: Sequence[Mapping[KT, VT]]) -> Mapping[KT, List[VT]]: + ret: Mapping[KT, List[VT]] = {} + for i, _dict in enumerate(arrayOfDicts): + if i == 0: + ret.update({key: [value] for key, value in _dict.items()}) + else: + assert set(ret.keys()) == set(_dict.keys()), "Keys should be the same" + for key, value in _dict.items(): + ret[key].append(value) + return ret + + +class TilingHoistingMixIn: + + _DEFAULT_HOIST_PREFIX = "TILING_CODEGEN_" + + def __init__(self, memory: str) -> None: + self.memory = memory + self._prefix = None + + def _initPrefix(self, nodeName: str) -> None: + self._prefix = f"{self._DEFAULT_HOIST_PREFIX}{self.memory}_{nodeName}_" + + def _deinitPrefix(self) -> None: + self._prefix = None + + @property + def prefix(self) -> str: + assert self._prefix is not None, "Prefix is not initialized!" + return self._prefix + + def _hoistValues(self, + ctxt: NetworkContext, + name: str, + values: List[int], + override_type: Optional[Type[BaseType]] = None) -> ConstantBuffer: + assert all(isinstance(value, int) for value in values) + cb = ctxt.ConstantBuffer(self.prefix + name, [len(values)], values) + ctxt.add(cb, 'global') + if override_type is not None: + cb._type = PointerClass(override_type) + else: + cb._type = PointerClass(BasicDataTypes.minimalIntegerType(values)) + cb._instance = cb._type(cb.name, ctxt) + cb._memoryLevel = self.memory + return cb + + def _hoistReference(self, + ctxt: NetworkContext, + name: str, + reference: VariableBuffer, + shape: Tuple[int, ...] = (1,), + offset: Union[int, str, VariableBuffer] = 0, + override_type: Optional[Type[BaseType]] = None) -> _ReferenceBuffer: + ref = ctxt.hoistReference(self.prefix + name, reference, shape, offset, override_type) + ref._memoryLevel = self.memory + return ref + + def _hoistTileNumAndIdxPtr(self, ctxt: NetworkContext, + tilingSchedules: List[TilingSchedule]) -> Tuple[ConstantBuffer, VariableBuffer]: + stepsNumTiles = [len(tilingSchedule.outputLoadSchedule) for tilingSchedule in tilingSchedules] + + cumulativeNumTiles = [0] + for numTiles in stepsNumTiles: + cumulativeNumTiles.append(cumulativeNumTiles[-1] + numTiles) + + tileNum = self._hoistValues(ctxt, "numTiles", cumulativeNumTiles) + + tileIdxPtr = ctxt.VariableBuffer(f"{self.prefix}tileIdxPtr", shape = [1]) + ctxt.add(tileIdxPtr, "local") + + tileIdxPtr._type = tileNum._type + tileIdxPtr._instance = tileIdxPtr._type(tileIdxPtr.name, ctxt) + # LMACAN: Intentionally don't annotate memory level so it gets allocated + # outside of the tiling loops + + tileIdxPtr.allocTemplate = NodeTemplate("") + tileIdxPtr.deallocTemplate = NodeTemplate("") + tileIdxPtr.initTemplate = NodeTemplate(""" + ${type.referencedType.typeName} bu_${name} = 0; + ${type.referencedType.typeName}* ${name} = &bu_${name};""") + + return (tileNum, tileIdxPtr) + + def _hoistOpReprUpdates(self, + ctxt: NetworkContext, + opReprs: List[OperatorRepresentation], + prefix: str = "") -> Tuple[OperatorRepresentation, List[str]]: + # Early exit if the opReprs list is empty because the following code assumes at least 1 opRepr is in the list + if len(opReprs) == 0: + return {}, [] + + newOpRepr = {} + hoistedReprNames = [] + for var, updates in dictOfArrays(opReprs).items(): + if all(update == updates[0] for update in updates): + newOpRepr[var] = updates[0] + else: + cb = self._hoistValues(ctxt, f"{prefix}{var}", updates) + newOpRepr[var] = cb.name + hoistedReprNames.append(var) + return newOpRepr, hoistedReprNames + + def _hoistMultibufferReferences(self, ctxt: NetworkContext, buffer: VariableBuffer, + tensorMemoryConstraint: TensorMemoryConstraint) -> List[_ReferenceBuffer]: + tensorName = tensorMemoryConstraint.tensorName + memoryConstraint = tensorMemoryConstraint.memoryConstraints[self.memory] + assert memoryConstraint.addrSpace is not None, "Assuming address space is set" + totalSize = memoryConstraint.addrSpace[1] - memoryConstraint.addrSpace[0] + assert isinstance(memoryConstraint.multiBufferCoefficient, + int), "Assuming multi buffer coefficient has been assigned" + assert totalSize % memoryConstraint.multiBufferCoefficient == 0, "Assuming total size is divisible by the multi buffer coefficient" + bufferSize = totalSize // memoryConstraint.multiBufferCoefficient + + assert memoryConstraint.multiBufferCoefficient == 2, "Multi buffer coefficient has to be equal to 2 since this is for double buffering" + assert memoryConstraint.shape is not None + assert len(memoryConstraint.shape) > 0 + assert isinstance(memoryConstraint.shape[0], int) + tileLength = math.prod(memoryConstraint.shape) + tileSize = int(math.ceil(tileLength * buffer._type.referencedType.typeWidth / 8)) + + assert bufferSize >= tileSize, f"Provided buffer size is not enough to fit the tile. Buffer size: {bufferSize}, tile size: {tileSize}" + + refs = [ + self._hoistReference( + ctxt, + f"{tensorName}_buffer_{i}", + buffer, + memoryConstraint.shape, + offset = i * bufferSize, + override_type = VoidType, + ) for i in range(memoryConstraint.multiBufferCoefficient) + ] + + return refs diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py index 6b4b297da3..b09192c5b7 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py @@ -36,7 +36,9 @@ class TilingMetaInfo: nodeName: str nodeOps: int - numTiles: int + numTiles: str + totalNumTiles: int + tileIdxPtr: str tileIdxVar: str kernelLevelTiling: bool @@ -44,16 +46,15 @@ class TilingMetaInfo: _CodeSegmentType = List[CodeSnippet] _measureCycles = NodeTemplate(""" -${nodeName}_${measurementName}_measurements[${tileIdx}] = getCycles(); +${measurements}[${tileIdxVar}] = getCycles(); """) _measurementArrayDeclaration = NodeTemplate(""" -uint32_t ${nodeName}_${measurementName}_measurements[${numTiles}]; +uint32_t ${measurements}[${totalNumTiles}]; """) -_printPrefixAndSufixDeclaration = NodeTemplate(""" -const static char ${nodeName}_prefix[] = "[${nodeName}][${buffering}][${nodeOps} ops][Tile "; -const static char ${nodeName}_suffix[] = " cycles \\n"; +_stringDeclaration = NodeTemplate(""" +const static char ${name}[] = "${string}"; """) _measureConditionSetup = NodeTemplate(""" @@ -66,17 +67,12 @@ class TilingMetaInfo: _printLoopSetup = NodeTemplate(""" StopTimer(); -<% -current_level_num = nodeName[-1] -lower_level_num = str(int(current_level_num) - 1) -%> -for (int printLoopIdx = DeeployNetwork_TILING_REPLACED_L${lower_level_num}_${nodeName[:-3]}_numTiles[*DeeployNetwork_TILING_REPLACED_L${lower_level_num}_${nodeName[:-3]}_tileIdxPtr -1]; - printLoopIdx < DeeployNetwork_TILING_REPLACED_L${lower_level_num}_${nodeName[:-3]}_numTiles[*DeeployNetwork_TILING_REPLACED_L${lower_level_num}_${nodeName[:-3]}_tileIdxPtr]; - printLoopIdx++){ +for (int ${profileIdxVar} = ${numTiles}[*${tileIdxPtr} -1]; ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; ${profileIdxVar}++){ """) + _printCycleDifference = NodeTemplate(r""" -printf("%s%u] %s%u%s", ${nodeName}_prefix,${tileIdx},"${flavorStr}", \ -${nodeName}_${endMeasurementName}_measurements[${tileIdx}] - ${nodeName}_${startMeasurementName}_measurements[${tileIdx}],${nodeName}_suffix); +printf("%s%u] %s%u%s", ${prefixStr}, ${profileIdxVar}, "${flavorStr}", \ +${measurementsEnd}[${profileIdxVar}] - ${measurementsStart}[${profileIdxVar}], ${suffixStr}); """) _printLoopTeardown = NodeTemplate(""" @@ -156,26 +152,30 @@ def measurementArrayDeclaration(cls, executionBlock: ExecutionBlock, metaInfo: T nodeName = metaInfo.nodeName numTiles = metaInfo.numTiles + totalNumTiles = metaInfo.totalNumTiles nodeOps = metaInfo.nodeOps - measurementNameList = [ + measurementsList = [ "ingress_dma_wait_start", "ingress_dma_wait_end", "egress_dma_wait_start", "egress_dma_wait_end" ] if metaInfo.kernelLevelTiling: - measurementNameList = ["kernel_start", "kernel_end"] + measurementNameList + measurementsList = ["kernel_start", "kernel_end"] + measurementsList - for measurementName in measurementNameList: + for measurements in measurementsList: executionBlock.addLeft(_measurementArrayDeclaration, { - "nodeName": nodeName, - "measurementName": measurementName, - "numTiles": numTiles + "measurements": f"{nodeName}_{measurements}_measurements", + "totalNumTiles": totalNumTiles }) - executionBlock.addLeft(_printPrefixAndSufixDeclaration, { - "nodeName": nodeName, - "nodeOps": nodeOps, - "buffering": bufferingStr + executionBlock.addLeft(_stringDeclaration, { + "name": f"{nodeName}_prefix", + "string": f"[{nodeName}][{bufferingStr}][{nodeOps} ops][Tile ", + }) + + executionBlock.addLeft(_stringDeclaration, { + "name": f"{nodeName}_suffix", + "string": " cycles \\n", }) return executionBlock @@ -185,33 +185,46 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe numTiles = metaInfo.numTiles nodeName = metaInfo.nodeName + tileIdxPtr = metaInfo.tileIdxPtr + totalNumTiles = metaInfo.totalNumTiles + profileIdxVar = "PROFILING_I" - executionBlock.addRight(_printLoopSetup, {"numTiles": numTiles, "nodeName": nodeName}) + executionBlock.addRight(_printLoopSetup, { + "numTiles": numTiles, + "nodeName": nodeName, + "profileIdxVar": profileIdxVar, + "tileIdxPtr": tileIdxPtr, + }) executionBlock.addRight( _printCycleDifference, { - "nodeName": nodeName, + "prefixStr": f"{nodeName}_prefix", + "suffixStr": f"{nodeName}_suffix", "flavorStr": "Input DMA took ", - "startMeasurementName": "ingress_dma_wait_start", - "endMeasurementName": "ingress_dma_wait_end", - "tileIdx": "printLoopIdx" + "measurementsStart": f"{nodeName}_ingress_dma_wait_start_measurements", + "measurementsEnd": f"{nodeName}_ingress_dma_wait_end_measurements", + "profileIdxVar": profileIdxVar, }) + if metaInfo.kernelLevelTiling: executionBlock.addRight( _printCycleDifference, { - "nodeName": nodeName, + "prefixStr": f"{nodeName}_prefix", + "suffixStr": f"{nodeName}_suffix", "flavorStr": "Kernel took ", - "startMeasurementName": "kernel_start", - "endMeasurementName": "kernel_end", - "tileIdx": "printLoopIdx" + "measurementsStart": f"{nodeName}_kernel_start_measurements", + "measurementsEnd": f"{nodeName}_kernel_end_measurements", + "profileIdxVar": profileIdxVar, }) + executionBlock.addRight( _printCycleDifference, { - "nodeName": nodeName, + "prefixStr": f"{nodeName}_prefix", + "suffixStr": f"{nodeName}_suffix", "flavorStr": "Output DMA took ", - "startMeasurementName": "egress_dma_wait_start", - "endMeasurementName": "egress_dma_wait_end", - "tileIdx": "printLoopIdx" + "measurementsStart": f"{nodeName}_egress_dma_wait_start_measurements", + "measurementsEnd": f"{nodeName}_egress_dma_wait_end_measurements", + "profileIdxVar": profileIdxVar, }) executionBlock.addRight(_printLoopTeardown, {}) @@ -225,14 +238,12 @@ def kernelProfilingWrap(cls, executionBlock: ExecutionBlock, metaInfo: TilingMet if metaInfo.kernelLevelTiling: executionBlock.addLeft(_measureCycles, { - "nodeName": nodeName, - "measurementName": "kernel_start", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_kernel_start_measurements", + "tileIdxVar": tileIdxVar }) executionBlock.addRight(_measureCycles, { - "nodeName": nodeName, - "measurementName": "kernel_end", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_kernel_end_measurements", + "tileIdxVar": tileIdxVar }) return executionBlock @@ -300,31 +311,27 @@ def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaI _ingressDMAWaitStatements = [] _ingressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "ingress_dma_wait_start", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar })) _ingressDMAWaitStatements += ingressDMAWaitStatements _ingressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "ingress_dma_wait_end", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar })) _egressDMAWaitStatements = [] _egressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_start", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_egress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar })) _egressDMAWaitStatements += egressDMAWaitStatements _egressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_end", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar })) executionBlock = super().generateInnerCode(executionBlock, metaInfo, ingressDMATransferCalls, @@ -374,27 +381,24 @@ def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: teardownStatements: _CodeSegmentType) -> ExecutionBlock: nodeName = metaInfo.nodeName - numTiles = metaInfo.numTiles + totalNumTiles = metaInfo.totalNumTiles executionBlock.addLeft(_measureCycles, { - "nodeName": nodeName, - "measurementName": "ingress_dma_wait_start", - "tileIdx": 0 + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": 0 }) executionBlock = cls.measurementArrayDeclaration(executionBlock, metaInfo, bufferingStr = "DB") executionBlock.addRight(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_start", - "tileIdx": numTiles - 1 + "measurements": f"{nodeName}_egress_dma_wait_start_measurements", + "tileIdxVar": totalNumTiles - 1 }) executionBlock = super().generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, teardownStatements) executionBlock.addRight(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_end", - "tileIdx": numTiles - 1 + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": totalNumTiles - 1 }) executionBlock = cls.injectPrintCycleDiff(executionBlock, metaInfo) @@ -417,33 +421,29 @@ def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaI _ingressDMAWaitStatements.append(CodeSnippet(_measureConditionSetup, {"cond": f"{tileIdxVar} > 0"})) _ingressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "ingress_dma_wait_start", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar })) _ingressDMAWaitStatements.append(CodeSnippet(_measureConditionEnd, {})) _ingressDMAWaitStatements += ingressDMAWaitStatements _ingressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "ingress_dma_wait_end", - "tileIdx": tileIdxVar + "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar })) _egressDMAWaitStatements = [] _egressDMAWaitStatements.append(CodeSnippet(_measureConditionSetup, {"cond": f"{tileIdxVar} > 0"})) _egressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_start", - "tileIdx": f"{tileIdxVar} - 1" + "measurements": f"{nodeName}_egress_dma_wait_start_measurements", + "tileIdxVar": f"{tileIdxVar} - 1" })) _egressDMAWaitStatements += egressDMAWaitStatements _egressDMAWaitStatements.append( CodeSnippet(_measureCycles, { - "nodeName": nodeName, - "measurementName": "egress_dma_wait_end", - "tileIdx": f"{tileIdxVar} - 1" + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": f"{tileIdxVar} - 1" })) _egressDMAWaitStatements.append(CodeSnippet(_measureConditionEnd, {})) diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py index fd910cc16b..3810260b75 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py @@ -24,192 +24,207 @@ # limitations under the License. import copy -from typing import Dict, List, Tuple, Type +import itertools +from typing import List, Tuple -from mako.parsetree import Expression, Node, Text - -from Deeploy.AbstractDataTypes import Pointer +from Deeploy.AbstractDataTypes import Struct from Deeploy.CommonExtensions.CodeTransformationPasses.Closure import ClosureExecutionBlock from Deeploy.CommonExtensions.CodeTransformationPasses.IntrospectiveCodeTransformation import \ IntrospectiveCodeTransformationMixIn from Deeploy.DeeployTypes import CodeGenVerbosity, CodeSnippet, CodeTransformationPass, ExecutionBlock, \ - NetworkContext, NodeTemplate, OperatorRepresentation, TransientBuffer, _NoVerbosity + NetworkContext, NodeTemplate, OperatorRepresentation, TransientBuffer, VariableBuffer, _NoVerbosity, \ + _ReferenceBuffer +from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import TilingHoistingMixIn from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint +from Deeploy.TilingExtension.TilerExtension import Tiler from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme, minimizeVariableReplacement -class TilingVariableReplacement(CodeTransformationPass, IntrospectiveCodeTransformationMixIn): - - _prefix = "TILING_REPLACED_" +class TilingVariableReplacement(CodeTransformationPass, IntrospectiveCodeTransformationMixIn, TilingHoistingMixIn): def __init__(self, targetMemLevel: str): self.targetMemLevel = targetMemLevel - self._name: str + TilingHoistingMixIn.__init__(self, targetMemLevel) @property - def prefix(self): - return self._prefix + f"{self._name}_" + self.targetMemLevel + "_" + def arenaName(self): + return f"{Tiler.arenaName}_{self.targetMemLevel}" - def _dereferencePointer(self, nodes: List[Node], name: str) -> List[Node]: - instanceIdxs = [idx for idx, node in enumerate(nodes) if isinstance(node, Expression) and node.text == name] + def _arenaAllocate(self, ctxt: NetworkContext, buffer: VariableBuffer, offset: int) -> VariableBuffer: + arena = ctxt.lookup(self.arenaName) + buffer.allocTemplate = NodeTemplate(" \ + ${type.typeName} ${name} = (${type.typeName}) " + f"((char*){str(arena._instance)} + {offset});") + buffer.deallocTemplate = NodeTemplate("") + return buffer - for offset, idx in enumerate(instanceIdxs): - text = Text("*", source = "*", lineno = 0, pos = 0, filename = None) - nodes.insert(offset + idx, text) - - return nodes + def _replaceTransients(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, + nodeMemoryConstraint: NodeMemoryConstraint) -> NetworkContext: + for value in operatorRepresentation.values(): + if not (isinstance(value, str) and ctxt.is_local(value)): + continue - def _replaceImmediate(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - variableReplacement: Tuple[str, - List], dataType: Type[Pointer]) -> Tuple[NetworkContext, Dict]: + buffer = ctxt.lookup(value) - varName = variableReplacement[0] - varVal = variableReplacement[1] + if not (isinstance(buffer, TransientBuffer) and buffer._memoryLevel == self.targetMemLevel): + continue - newConstName = self.prefix + varName - newRefName = self.prefix + "ref_" + varName + memoryConstraints = nodeMemoryConstraint.tensorMemoryConstraints[buffer.name].memoryConstraints + assert len(memoryConstraints) == 1, f"Tiled transient buffer {buffer.name} has more than one memory level!" + constraint = next(iter(memoryConstraints.values())) + assert constraint.addrSpace is not None, f"Address space of {constraint} cannot be None!" + offset = constraint.addrSpace[0] + self._arenaAllocate(ctxt, buffer, offset) - cb = ctxt.ConstantBuffer(newConstName, shape = (len(varVal),), values = varVal) - ctxt.add(cb, "global") + return ctxt - cb._type = dataType - cb._instance = dataType(newConstName, ctxt) - cb._memoryLevel = self.targetMemLevel + def _replaceVariableReplacements(self, ctxt: NetworkContext, snippet: CodeSnippet, + variableReplacement: VariableReplacementScheme) -> NetworkContext: + operatorRepresentation = snippet.operatorRepresentation + template = snippet.template - reference = ctxt.hoistReference(newConstName, newRefName) - ctxt.lookup(reference)._memoryLevel = self.targetMemLevel + replacedVars = [] - operatorRepresentation[varName] = reference + for name, values in variableReplacement.perTileReplacements.items(): + # Case where we have already replaced the variable + if isinstance(operatorRepresentation[name], str): + continue + _type = variableReplacement.replacementTypes[name] + # LMACAN: Hoist values expects integers (should be the only thing we deal with for now...) + intValues = [int(v) for v in values] + assert all(intV == v for intV, v in zip(intValues, values)), f"Received non-int values" + buff = self._hoistValues(ctxt, name, intValues, _type.referencedType) + ref = self._hoistReference(ctxt, name + "_ref", buff) + operatorRepresentation[name] = ref.name + replacedVars.append(name) - return ctxt, operatorRepresentation + self.dereferenceVars(template.template, replacedVars) - def _hoistTileReference(self, ctxt: NetworkContext, reference: str, name: str, offset: int) -> NetworkContext: + return ctxt - refName = ctxt.hoistReference(reference, name) - refBuf = ctxt.lookup(refName) + def _replaceTiledTensors(self, ctxt: NetworkContext, snippet: CodeSnippet, + tilingSchedule: TilingSchedule) -> NetworkContext: + operatorRepresentation = snippet.operatorRepresentation - staticBuf = ctxt.lookup(f"MEMORYARENA_{self.targetMemLevel}") + for name, offsets in itertools.chain(tilingSchedule.inputBaseOffsets.items(), + tilingSchedule.outputBaseOffsets.items()): + buffer = ctxt.lookup(operatorRepresentation[name]) + assert isinstance(buffer, VariableBuffer) + unraveledBuffer = ctxt.unravelReference(buffer) - refBuf.allocTemplate = NodeTemplate(" \ - ${type.typeName} ${name} = (${type.typeName}) " + f"((char*){str(staticBuf._instance)} + {offset});") - refBuf._memoryLevel = self.targetMemLevel + ref = self._hoistReference(ctxt, name + "_ref", unraveledBuffer) + ref = self._arenaAllocate(ctxt, ref, offsets[0]) + operatorRepresentation[name] = ref.name return ctxt - def _replaceReferences(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - tilingSchedule: TilingSchedule, name: str) -> Tuple[NetworkContext, Dict]: + def apply(self, + ctxt: NetworkContext, + executionBlock: ExecutionBlock, + name: str, + verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: + self._initPrefix(name) - def unravelOldRef(refName): - oldBuf = ctxt.lookup(refName) - if hasattr(oldBuf, "_referenceName"): - return unravelOldRef(oldBuf._referenceName) - return oldBuf.name + if isinstance(executionBlock, ClosureExecutionBlock): + baseExecutionBlock = executionBlock.baseBlock + else: + baseExecutionBlock = executionBlock - newRefName = self.prefix + "ref_" + name - oldRefName = operatorRepresentation[name] + patternMemoryConstraint = baseExecutionBlock.patternMemoryConstraint - if name in tilingSchedule.inputBaseOffsets: - offset = tilingSchedule.inputBaseOffsets[name] - elif name in tilingSchedule.outputBaseOffsets: - offset = tilingSchedule.outputBaseOffsets[name] - else: - raise RuntimeError(f"Name {name} not found in TilingSchedule {tilingSchedule}") + if patternMemoryConstraint is None: + return ctxt, executionBlock - unravelRef = unravelOldRef(oldRefName) + assert len(patternMemoryConstraint.nodeConstraints) == 1, "Only layerwise supported for now!" + #assert len(executionBlock.codeSnippets) == 1, "Only layerwise supported for now!" - ctxt = self._hoistTileReference(ctxt, unravelRef, newRefName, offset[0]) - operatorRepresentation[name] = newRefName + nodeMemoryConstraint = patternMemoryConstraint.nodeConstraints[0] - return ctxt, operatorRepresentation + possibleSnippets = [ + node for node in baseExecutionBlock.codeSnippets if hasattr(node.template, 'tileConstraint') + ] - def _replaceTransients(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation, - nodeMemoryConstraint: NodeMemoryConstraint, name: str) -> Tuple[NetworkContext, Dict]: + assert len(possibleSnippets) == 1, "More than one template node with TCF found" - memoryConstraints = nodeMemoryConstraint.tensorMemoryConstraints[operatorRepresentation[name]].memoryConstraints - assert len(memoryConstraints - ) == 1, f"Tiled transient buffer {operatorRepresentation[name]} has more than one memory level!" - key = list(memoryConstraints.keys())[0] - constraint = memoryConstraints[key] - assert constraint.addrSpace is not None, f"Address space of {constraint} cannot be None!" - offset = constraint.addrSpace[0] + snippet = possibleSnippets[0] + operatorRepresentation = snippet.operatorRepresentation + template = snippet.template - refBuf = ctxt.lookup(operatorRepresentation[name]) + unraveledOpRepr = { + key: ctxt.unravelReference(ctxt.lookup(value)).name if ctxt.is_buffer(value) else value + for key, value in operatorRepresentation.items() + } - if refBuf._memoryLevel != self.targetMemLevel: - return ctxt, operatorRepresentation + variableReplacement, tilingSchedules = template.tileConstraint.wrapTilingSolution( + nodeMemoryConstraint, self.targetMemLevel, ctxt, unraveledOpRepr) - staticBuf = ctxt.lookup(f"MEMORYARENA_{self.targetMemLevel}") + minimalVariableReplacement, newOpRepr = minimizeVariableReplacement(variableReplacement, operatorRepresentation) + operatorRepresentation.update(newOpRepr) - refBuf.allocTemplate = NodeTemplate(" \ - ${type.typeName} ${name} = (${type.typeName}) " + f"((char*){str(staticBuf._instance)} + {offset});") - refBuf.deallocTemplate = NodeTemplate("") - refBuf._memoryLevel = self.targetMemLevel + flatTilingSchedule = copy.copy(tilingSchedules[0]) + for tilingSchedule in tilingSchedules[1:]: + flatTilingSchedule += tilingSchedule - return ctxt, operatorRepresentation + ctxt = self._replaceVariableReplacements(ctxt, snippet, minimalVariableReplacement) + ctxt = self._replaceTiledTensors(ctxt, snippet, flatTilingSchedule) + ctxt = self._replaceTransients(ctxt, operatorRepresentation, nodeMemoryConstraint) - def _replaceTiledExpressions(self, ctxt: NetworkContext, templateNode: CodeSnippet, - variableReplacement: VariableReplacementScheme, tilingSchedule: TilingSchedule, - nodeMemoryConstraint: NodeMemoryConstraint) -> NetworkContext: + tilingReplacedRefMap = {} + for key in list(flatTilingSchedule.inputBaseOffsets.keys()) + list(flatTilingSchedule.outputBaseOffsets.keys()): + tilingReplacedRefMap[unraveledOpRepr[key]] = operatorRepresentation[key] - operatorRepresentation = templateNode.operatorRepresentation - template = templateNode.template + # Swap any original tensor occurances with the tiled targetMemLevel-local tensor + for codeSnippet in executionBlock.codeSnippets: + template, opRepr = codeSnippet.template, codeSnippet.operatorRepresentation - immediateList = [(key, value) - for key, value in variableReplacement.perTileReplacements.items() - if type(operatorRepresentation[key]) != str] + for key, value in opRepr.items(): + if isinstance(value, str) and value in tilingReplacedRefMap: + opRepr[key] = tilingReplacedRefMap[value] - inoutSchedule = {**tilingSchedule.inputBaseOffsets, **tilingSchedule.outputBaseOffsets} - variableList = [key for key, value in inoutSchedule.items() if type(operatorRepresentation[key]) == str] + if "closureStructArgs" in opRepr: + closureArgsStruct: Struct = opRepr['closureStructArgs'] + structDict = closureArgsStruct.value - transientBufferList = [] - for key, value in operatorRepresentation.items(): - if not isinstance(value, str): - continue - if (ctxt.is_local(value) and isinstance(ctxt.lookup(value), TransientBuffer)): - transientBufferList.append(key) + for key, value in structDict.items(): + if value.referenceName in tilingReplacedRefMap: + structDict[key] = type(value)(tilingReplacedRefMap[value.referenceName], ctxt) - parseTree = IntrospectiveCodeTransformationMixIn._generateParseTree(template) - newParseTree = copy.copy(parseTree) - nodes = parseTree.nodes + self._deinitPrefix() - newNodes = copy.copy(nodes) + return ctxt, executionBlock - for rep in immediateList: - ctxt, operatorRepresentation = self._replaceImmediate(ctxt, operatorRepresentation, rep, - variableReplacement.replacementTypes[rep[0]]) - newNodes = self._dereferencePointer(newNodes, rep[0]) - for rep in variableList: - ctxt, operatorRepresentation = self._replaceReferences(ctxt, operatorRepresentation, tilingSchedule, rep) +class TilingVariableReplacementUpdate(CodeTransformationPass, IntrospectiveCodeTransformationMixIn, + TilingHoistingMixIn): - for rep in transientBufferList: - ctxt, operatorRepresentation = self._replaceTransients(ctxt, operatorRepresentation, nodeMemoryConstraint, - rep) + _updateReferenceTemplate = NodeTemplate(""" + // UPDATE VARIABLE ${reference} + *${reference} = ${baseReference}[${tileIdxVar}]; + """) - newParseTree.nodes = newNodes - IntrospectiveCodeTransformationMixIn._reconstructCode(template, newParseTree) + def __init__(self, targetMemLevel: str, tileIdxVar: str = "TILING_I"): + super().__init__() + self.tileIdxVar = tileIdxVar + self.targetMemLevel = targetMemLevel - return ctxt + def _generateVariableUpdates(self, variableReplacement: VariableReplacementScheme, ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation) -> List[CodeSnippet]: + updates = [] + for key in variableReplacement.perTileReplacements.keys(): + ref = ctxt.lookup(operatorRepresentation[key]) + assert isinstance(ref, _ReferenceBuffer) + updates.append( + CodeSnippet(self._updateReferenceTemplate, { + "reference": ref.name, + "tileIdxVar": self.tileIdxVar, + "baseReference": ref._referenceName + })) + return updates def apply(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: - - def unravelReference(ctxt: NetworkContext, name: str) -> str: - - if name not in ctxt.localObjects.keys() and name not in ctxt.globalObjects.keys(): - return name - - refBuffer = ctxt.lookup(name) - if not hasattr(refBuffer, "_referenceName"): - return name - - return unravelReference(ctxt, refBuffer._referenceName) - - self._name = name - if isinstance(executionBlock, ClosureExecutionBlock): baseExecutionBlock = executionBlock.baseBlock else: @@ -221,61 +236,33 @@ def unravelReference(ctxt: NetworkContext, name: str) -> str: return ctxt, executionBlock assert len(patternMemoryConstraint.nodeConstraints) == 1, "Only layerwise supported for now!" - #assert len(executionBlock.codeSnippets) == 1, "Only layerwise supported for now!" nodeMemoryConstraint = patternMemoryConstraint.nodeConstraints[0] - possibleTemplateNodes = [ + possibleSnippets = [ node for node in baseExecutionBlock.codeSnippets if hasattr(node.template, 'tileConstraint') ] - assert len(possibleTemplateNodes) == 1, "More than one template node with TCF found" - - templateNode = possibleTemplateNodes[0] - operatorRepresentation = templateNode.operatorRepresentation - - unravelRep = operatorRepresentation.copy() - for key in unravelRep.keys(): + assert len(possibleSnippets) == 1, "More than one template node with TCF found" - val = unravelRep[key] - if not isinstance(val, str): - continue - - unravelRep[key] = unravelReference(ctxt, val) + snippet = possibleSnippets[0] + operatorRepresentation = snippet.operatorRepresentation + template = snippet.template - template = templateNode.template - - variableReplacement, tilingSchedules = template.tileConstraint.wrapTilingSolution( - nodeMemoryConstraint, self.targetMemLevel, ctxt, unravelRep) + unraveledOpRepr = { + key: ctxt.unravelReference(ctxt.lookup(value)).name if ctxt.is_buffer(value) else value + for key, value in operatorRepresentation.items() + } - minimalVariableReplacement, newNodeRep = minimizeVariableReplacement(variableReplacement, - templateNode.operatorRepresentation) - for key, value in newNodeRep.items(): - templateNode.operatorRepresentation[key] = value + variableReplacement, _ = template.tileConstraint.wrapTilingSolution(nodeMemoryConstraint, self.targetMemLevel, + ctxt, unraveledOpRepr) - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule + minimalVariableReplacement, newOpRepr = minimizeVariableReplacement(variableReplacement, operatorRepresentation) + operatorRepresentation.update(newOpRepr) - ctxt = self._replaceTiledExpressions(ctxt, templateNode, minimalVariableReplacement, flatTilingSchedule, - nodeMemoryConstraint) + updates = self._generateVariableUpdates(minimalVariableReplacement, ctxt, operatorRepresentation) - for codeSnippet in executionBlock.codeSnippets: + for snippet in updates: + executionBlock.addLeft(snippet.template, snippet.operatorRepresentation) - template, nRep = codeSnippet.template, codeSnippet.operatorRepresentation - - if not "closureStructArgs" in nRep: - continue - - keyList = {} - - for key in list(flatTilingSchedule.inputBaseOffsets.keys()) + list( - flatTilingSchedule.outputBaseOffsets.keys()): - keyList[unravelRep[key]] = operatorRepresentation[key] - - for key in copy.copy(nRep['closureStructArgs'].value).keys(): - if nRep['closureStructArgs'].value[key].referenceName in keyList.keys(): - nRep['closureStructArgs'].value[key] = type(nRep['closureStructArgs'].value[key])( - keyList[nRep['closureStructArgs'].value[key].referenceName], ctxt) - - return ctxt, executionBlock + return super().apply(ctxt, executionBlock, name, verbose) diff --git a/Deeploy/TilingExtension/MemoryConstraints.py b/Deeploy/TilingExtension/MemoryConstraints.py index 0c12368250..60d035ae1a 100644 --- a/Deeploy/TilingExtension/MemoryConstraints.py +++ b/Deeploy/TilingExtension/MemoryConstraints.py @@ -42,7 +42,7 @@ def __init__(self, memoryLevel: str, size: Union[IntVar, int]): self.size: Union[int, IntVar] = size self.multiBufferCoefficient: Union[int, IntVar] = 1 - self.shape: Optional[Tuple[int]] = None + self.shape: Optional[Tuple[int, ...]] = None self.addrSpace: Optional[Tuple[int, int]] = None def __repr__(self) -> str: diff --git a/Deeploy/TilingExtension/MemoryScheduler.py b/Deeploy/TilingExtension/MemoryScheduler.py index a6f6a75bc4..cc0df4846d 100644 --- a/Deeploy/TilingExtension/MemoryScheduler.py +++ b/Deeploy/TilingExtension/MemoryScheduler.py @@ -33,8 +33,7 @@ import numpy as np from ortools.constraint_solver.pywrapcp import IntVar -from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ - _permuteList +from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import _permute from Deeploy.DeeployTypes import ConstantBuffer, NetworkContext, TransientBuffer from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy from Deeploy.TilingExtension.MemoryConstraints import PatternMemoryConstraints, TensorMemoryConstraint @@ -540,7 +539,7 @@ def scheduleMemoryConstraints(self, def constraintTileBuffersWithOverlappingLifetime(self, tilerModel: TilerModel, ctxt: NetworkContext, patternMemoryConstraint: PatternMemoryConstraints, memoryHierarchy: MemoryHierarchy): - """This method adds the necessay constraints for tiling to be performed before the static memory allocation of the tile buffers. + """This method adds the necessary constraints for tiling to be performed before the static memory allocation of the tile buffers. To perform static memory allocation after tiling (i.e. decouple tiling and memory alloc), we need to do two assumptions 1. All tile buffers for each node have overlapping lifetime, so we can find their memory footprint by just summing their sizes and hence we don't need to know the specific memory allocation. This assumption is true as soon as we don't do tile several nodes together (ask me if you don't know what I mean here). @@ -659,7 +658,7 @@ def permMatrix2permList(permMatrix: np.ndarray) -> List[int]: permList = permMatrix2permList(_permutationMatrix) if pattern != [] and len(pattern) > 1: - permPattern = _permuteList(pattern, permList) + permPattern = _permute(pattern, permList) else: permPattern = pattern diff --git a/Deeploy/TilingExtension/TileConstraint.py b/Deeploy/TilingExtension/TileConstraint.py index eed22b0961..e73cd3b615 100644 --- a/Deeploy/TilingExtension/TileConstraint.py +++ b/Deeploy/TilingExtension/TileConstraint.py @@ -31,12 +31,11 @@ import numpy as np from ortools.constraint_solver.pywrapcp import IntVar -#from Deeploy import TilerModel from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation from Deeploy.TilingExtension.MemoryConstraints import MemoryConstraint, NodeMemoryConstraint, TensorMemoryConstraint from Deeploy.TilingExtension.TilerModel import TilerModel from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle, MemoryTransfer, \ - TilingSchedule, VariableReplacementScheme, computeHyperRectangleList + TilingSchedule, VariableReplacementScheme, computeTileHyperRectangles class TileConstraint(): @@ -65,19 +64,15 @@ def constructSymbolicNodeRep(tilerModel: TilerModel, parseDict: Dict, @staticmethod def getBaseAddr(tilingSolution, targetMemLevel, name) -> List[Optional[int]]: + mc = tilingSolution.tensorMemoryConstraints[name].memoryConstraints[targetMemLevel] - block = tilingSolution.tensorMemoryConstraints[name].memoryConstraints[targetMemLevel] - - if block.addrSpace is None: + if mc.addrSpace is None: return [None] - baseAddr = block.addrSpace[0] - endAddr = block.addrSpace[1] - sol = [] - for it in range(block.multiBufferCoefficient): - addr = ((endAddr - baseAddr) // block.multiBufferCoefficient) * it + baseAddr - sol.append(addr) - return sol + start, end = mc.addrSpace + bufferSize = (end - start) // mc.multiBufferCoefficient + + return [start + bufferSize * i for i in range(mc.multiBufferCoefficient)] @staticmethod def extractBaseAddr(tilingSolution: NodeMemoryConstraint, targetMemLevel: str, @@ -102,9 +97,6 @@ def extractBaseAddr(tilingSolution: NodeMemoryConstraint, targetMemLevel: str, @staticmethod def sanitizeTilingSchedule(tilingSchedule: TilingSchedule) -> TilingSchedule: - - _tilingSchedule = tilingSchedule - for baseOffsetName, baseOffsetValue in tilingSchedule.inputBaseOffsets.copy().items(): if baseOffsetValue == [None]: for step in tilingSchedule.inputLoadSchedule: @@ -117,7 +109,7 @@ def sanitizeTilingSchedule(tilingSchedule: TilingSchedule) -> TilingSchedule: del step[baseOffsetName] del tilingSchedule.outputBaseOffsets[baseOffsetName] - return _tilingSchedule + return tilingSchedule @classmethod def wrapTilingSolution( @@ -144,14 +136,13 @@ def _offsetAdd(offsetA: Tuple[int, ...], offsetB: Tuple[int, ...]) -> Tuple[int, def getCubeTransfers(tensorConstraint: TensorMemoryConstraint, sourceCubes: List[AbsoluteHyperRectangle], sourceMemoryLevel: str, targetMemoryLevel: str) -> Tuple[List[AbsoluteHyperRectangle], List[int]]: - solution = [] solutionLengths = [] for sourceCube in sourceCubes: memTransfer = getMemoryTransfer(tensorConstraint, sourceCube.rectangle, sourceMemoryLevel, targetMemoryLevel) - solutionCubes = computeHyperRectangleList(memTransfer) + solutionCubes = computeTileHyperRectangles(memTransfer) solutionAbsoluteCubes = [ AbsoluteHyperRectangle(rectangle = cube, absoluteOffset = _offsetAdd(sourceCube.absoluteOffset, cube.offset)) @@ -162,32 +153,29 @@ def getCubeTransfers(tensorConstraint: TensorMemoryConstraint, sourceCubes: List return solution, solutionLengths - assert len(tilingSolution.outputTensorMemoryConstraints.keys()) == 1, "Expected node to have only one output!" - varOut = list(tilingSolution.outputTensorMemoryConstraints.keys())[0] + assert len(tilingSolution.outputTensorMemoryConstraints) == 1, "Expected node to have only one output!" + + outVar, outTensorConstraint = next(iter(tilingSolution.outputTensorMemoryConstraints.items())) + memoryPath = list(outTensorConstraint.memoryConstraints.keys()) - outTensorConstraint = tilingSolution.tensorMemoryConstraints[varOut] - outTensorMemoryLevelPath = list(outTensorConstraint.memoryConstraints.keys()) - targetIdxs = [idx for idx, key in enumerate(outTensorMemoryLevelPath) if key == targetMemLevel] + assert targetMemLevel in memoryPath, \ + f"Target memory level {targetMemLevel} does not exist in the memory path {memoryPath}" - assert len(targetIdxs) == 1, f"Received more than one spec for memoryLevel {targetMemLevel}" - targetIdx = targetIdxs[0] + targetIdx = memoryPath.index(targetMemLevel) if targetIdx == 0: # SCHEREMO: Watch out - this happens if inputs are in L(N+1) but outputs only in L(N) targetIdx = 1 - fullShape = ctxt.lookup(varOut).shape - initialOffset = tuple([0] * len(fullShape)) + fullShape = ctxt.lookup(outVar).shape + initialOffset = (0,) * len(fullShape) outputCubes = [ AbsoluteHyperRectangle(rectangle = HyperRectangle(offset = initialOffset, dims = tuple(fullShape)), absoluteOffset = initialOffset) ] - for targetIdx in list(range(targetIdx + 1))[1:]: - sourceMemoryLevel = outTensorMemoryLevelPath[targetIdx - 1] - targetMemoryLevel = outTensorMemoryLevelPath[targetIdx] - outputCubes, solutionLengths = getCubeTransfers(outTensorConstraint, outputCubes, sourceMemoryLevel, - targetMemoryLevel) + for source, target in zip(memoryPath[:targetIdx], memoryPath[1:targetIdx + 1]): + outputCubes, solutionLengths = getCubeTransfers(outTensorConstraint, outputCubes, source, target) arrayOfCubes = [] _idx = 0 diff --git a/Deeploy/TilingExtension/TilerExtension.py b/Deeploy/TilingExtension/TilerExtension.py index abd3e38329..0e79178c28 100644 --- a/Deeploy/TilingExtension/TilerExtension.py +++ b/Deeploy/TilingExtension/TilerExtension.py @@ -58,6 +58,7 @@ from Deeploy.TilingExtension.TilerModel import TilerModel TilingSolution = List[PatternMemoryConstraints] +MemoryMap = Dict[str, List[List[MemoryBlock]]] _deallocTemplate = NodeTemplate("") @@ -307,17 +308,17 @@ def minimalloc(self, memoryMap, ctxt, nodeMemoryConstraint, capacity: int, memor return memoryMap - def computeTilingSchedule(self, ctxt: NetworkContext) -> Tuple[TilingSolution, Dict[str, List[List[MemoryBlock]]]]: - + def computeTilingSchedule(self, ctxt: NetworkContext) -> TilingSolution: assert self.tilerModel is not None and self.symbolicMemoryConstraints is not None, "Set up the model before trying to compute a schedule!" - collector = self.tilerModel.trySolveModel() - tilingSchedule = self._getTilingSolution(self.tilerModel, ctxt, collector, self.symbolicMemoryConstraints) - + tilingSolution = self._getTilingSolution(self.tilerModel, ctxt, collector, self.symbolicMemoryConstraints) if not self.memoryAllocStrategy == "MiniMalloc": + assert self.tilerModel is not None self.innerMemoryScheduler.annotateSolution(ctxt, self.tilerModel) self.outerMemoryScheduler.annotateSolution(ctxt, self.tilerModel) + return tilingSolution + def computeMemoryMap(self, ctxt: NetworkContext, tilingSolution: TilingSolution) -> MemoryMap: memoryMap = {} for key in self.innerMemoryScheduler.memoryMap.keys(): @@ -334,11 +335,16 @@ def computeTilingSchedule(self, ctxt: NetworkContext) -> Tuple[TilingSolution, D for idx, memMap in enumerate(memoryMap[memoryLevel]): if len(memoryMap[memoryLevel][idx]) != 0: memoryMap[memoryLevel][idx] = self.minimalloc( - memMap, ctxt, tilingSchedule[idx].nodeConstraints[0], + memMap, ctxt, tilingSolution[idx].nodeConstraints[0], self.memoryHierarchy.memoryLevels[memoryLevel].size - constantTensorOffset, memoryLevel) + print(f"\033[92mMemory allocation sucessful!\033[0m") - for idx, pattern in enumerate(tilingSchedule): + return memoryMap + + def annotateMemoryLevel(self, ctxt: NetworkContext, tilingSolution: TilingSolution, + memoryMap: Dict) -> NetworkContext: + for idx, pattern in enumerate(tilingSolution): for nodeIdx, nodeConstraint in enumerate(pattern.nodeConstraints): for tensorConstraint in nodeConstraint.tensorMemoryConstraints.values(): for memoryConstraint in tensorConstraint.memoryConstraints.values(): @@ -359,10 +365,7 @@ def computeTilingSchedule(self, ctxt: NetworkContext) -> Tuple[TilingSolution, D block = _block[0] memoryConstraint.addrSpace = block.addrSpace - - self._convertCtxtToStaticSchedule(ctxt, memoryMap) - - return tilingSchedule, memoryMap + return ctxt def setupModel(self, ctxt: NetworkContext, schedule: Schedule, layerBinding: OrderedDict[str, ONNXLayer], targetMemoryLevelMapping: TargetMemoryLevelMapping) -> NetworkContext: @@ -911,6 +914,19 @@ def assertUniformMemoryLevelAllocation(self, ctxt: NetworkContext, defaultMemory return False return True + def testTilingSolutionCorrectness(self, tilingSolution: TilingSolution) -> None: + # LMACAN: Assert buffer sizes are word aligned as per comment in MemoryScheduler.py:MemoryScheduler._buildCostVector() + byteAlignment = MemoryScheduler.byteAlignment + for patternMemoryConstraint in tilingSolution: + for nodeMemoryConstraint in patternMemoryConstraint.nodeConstraints: + for tensorMemoryConstraint in nodeMemoryConstraint.tensorMemoryConstraints.values(): + for memoryConstraint in tensorMemoryConstraint.memoryConstraints.values(): + if memoryConstraint.addrSpace is not None: + assert isinstance(memoryConstraint.multiBufferCoefficient, int) + bufferSize = (memoryConstraint.addrSpace[1] - + memoryConstraint.addrSpace[0]) // memoryConstraint.multiBufferCoefficient + assert bufferSize % byteAlignment == 0, f"Buffer in {memoryConstraint} is not {byteAlignment} byte aligned" + def testMemoryMapCorrectness(self, memoryMap: Dict[str, List[List[MemoryBlock]]], graph: gs.Graph, schedule: Schedule) -> None: @@ -919,8 +935,8 @@ def testMemoryMapCorrectness(self, memoryMap: Dict[str, List[List[MemoryBlock]]] } # JUNGVI: Assert output buffers are alive until the end - for outputBuffer in graph.outputs: - assert memoryBlockMap[outputBuffer.name]._lifetime[-1] == len( + for tensor in graph.outputs: + assert memoryBlockMap[tensor.name]._lifetime[-1] == len( schedule), "Invalid memory map! Output buffer is not alive at the last step!" # JUNGVI: Assert input buffers are alive at the beginning @@ -956,10 +972,13 @@ def worstCaseBufferSize(self): return maxAddr - def tile(self, tilingSolution: Optional[TilingSolution] = None): - if tilingSolution is None: - schedule = self.scheduler(self.graph) + def tile(self, tilingSolution: Optional[TilingSolution] = None, memoryMap: Optional[MemoryMap] = None): + assert (tilingSolution is None and memoryMap is None) or (tilingSolution is not None and memoryMap is not None), \ + "You need to provide both the manual tilingSolution and the memoryMap to override tiling." + + schedule = self.scheduler(self.graph) + if tilingSolution is None and memoryMap is None: # JUNGVI: Currently using MiniMalloc is only supported for layer-wise execution and all tensors in the default memory level. if self.tiler.memoryAllocStrategy == "MiniMalloc": assert self.tiler.assertLayerWiseTiling(schedule), "Using MiniMalloc and DFT is not supported!" @@ -971,11 +990,22 @@ def tile(self, tilingSolution: Optional[TilingSolution] = None): schedule = schedule, layerBinding = self.layerBinding, targetMemoryLevelMapping = self.getTargetMemoryLevelMapping()) - tilingSolution, memoryMap = self.tiler.computeTilingSchedule(self.ctxt) - if self.tiler.visualizeMemoryAlloc: - self.tiler.plotMemoryAlloc(memoryMap, self.ctxt, self.deeployStateDir, self.Platform.memoryHierarchy) + tilingSolution = self.tiler.computeTilingSchedule(self.ctxt) + + memoryMap = self.tiler.computeMemoryMap(self.ctxt, tilingSolution) + + assert tilingSolution is not None and memoryMap is not None + + self.tiler.testTilingSolutionCorrectness(tilingSolution) + + self.tiler.annotateMemoryLevel(self.ctxt, tilingSolution, memoryMap) + + self.ctxt = self.tiler._convertCtxtToStaticSchedule(self.ctxt, memoryMap) + + if self.tiler.visualizeMemoryAlloc: + self.tiler.plotMemoryAlloc(memoryMap, self.ctxt, self.deeployStateDir, self.Platform.memoryHierarchy) - self.tiler.testMemoryMapCorrectness(memoryMap, self.graph, schedule) + self.tiler.testMemoryMapCorrectness(memoryMap, self.graph, schedule) # SCHEREMO: Annotate execution block with solution for layer, pattern in zip(self.layerBinding.values(), tilingSolution): diff --git a/Deeploy/TilingExtension/TilingCodegen.py b/Deeploy/TilingExtension/TilingCodegen.py index 6a2ff26674..37e032064a 100644 --- a/Deeploy/TilingExtension/TilingCodegen.py +++ b/Deeploy/TilingExtension/TilingCodegen.py @@ -26,12 +26,13 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Dict, Iterable, List, Optional, Tuple, Type +from typing import Dict, Generator, List, Sequence, Tuple, Type import numpy as np from Deeploy.AbstractDataTypes import Pointer -from Deeploy.TilingExtension.MemoryConstraints import MemoryConstraint, NodeMemoryConstraint +from Deeploy.DeeployTypes import OperatorRepresentation, VariableBuffer +from Deeploy.TilingExtension.MemoryConstraints import MemoryConstraint @dataclass @@ -194,177 +195,117 @@ def minimizeVariableReplacement( return VariableReplacementScheme(newPerTileRep, newRepTypes), operatorRepresentation -def minimizeRectangleDims(hyperRectangle: HyperRectangle, - referenceBuffer: VariableBuffer) -> Tuple[HyperRectangle, HyperRectangle]: - - rectDims = hyperRectangle.dims - rectOffset = hyperRectangle.offset - shape = referenceBuffer.shape - newDims: List[int] = [] - newOffset: List[int] = [] - - newBaseline = [] - - reversedRectOffset = list(reversed(rectOffset)) +def minimizeRectangle(rect: HyperRectangle, referenceShape: Sequence[int]) -> Tuple[HyperRectangle, Tuple[int, ...]]: + minRectShape: List[int] = [] + minRectOffset: List[int] = [] + minReferenceShape: List[int] = [] # SCHEREMO: Collapse dimensions right to left - acc = 0 - for idx, (tileDim, bufDim) in enumerate(zip(reversed(rectDims), reversed(shape))): - - if tileDim == bufDim: - assert reversedRectOffset[idx] == 0, "Can't not tile a dimension and have an offset, tf" - - # SCHEREMO: Collapse if equal - if tileDim == bufDim and acc != 0: - acc *= tileDim - elif tileDim == bufDim and acc == 0: - acc = tileDim - elif tileDim != bufDim and acc != 0: - newDims.insert(0, acc * tileDim) - newBaseline.insert(0, acc * bufDim) - newOffset.insert(0, acc * reversedRectOffset[idx]) - acc = 0 + currentCollapsedDim = 1 + for rectDim, rectOffset, referenceDim in zip(reversed(rect.dims), reversed(rect.offset), reversed(referenceShape)): + if rectDim == referenceDim: + assert rectOffset == 0, f"Rectangle offset should be zero when the dimensions are the same. Received rectangle {rect} and reference shape {referenceShape}" + currentCollapsedDim *= rectDim else: - newDims.insert(0, tileDim) - newBaseline.insert(0, bufDim) - newOffset.insert(0, reversedRectOffset[idx]) - - if acc > 1: - newDims.insert(0, acc) - newBaseline.insert(0, acc) - newOffset.insert(0, acc * reversedRectOffset[idx]) - - # JUNGVI: If the function collapsed all dimensions of the tensor, set it to dim 1 and offset 0 - if len(newDims) == 0: - newDims = [1] - newBaseline = [1] - newOffset = [0] + minRectShape.insert(0, currentCollapsedDim * rectDim) + minReferenceShape.insert(0, currentCollapsedDim * referenceDim) + minRectOffset.insert(0, currentCollapsedDim * rectOffset) + currentCollapsedDim = 1 - newRect = HyperRectangle(tuple(newOffset), tuple(newDims)) - newBaseline = HyperRectangle(tuple([0] * len(newOffset)), tuple(newBaseline)) + if currentCollapsedDim > 1 or len(minRectShape) == 0: + minRectShape.insert(0, currentCollapsedDim) + minReferenceShape.insert(0, currentCollapsedDim) + minRectOffset.insert(0, currentCollapsedDim * rect.offset[0]) - return newRect, newBaseline + return HyperRectangle(tuple(minRectOffset), tuple(minRectShape)), tuple(minReferenceShape) -def calculateRectangleOffset(hyperRectangle: HyperRectangle, referenceBuffer: VariableBuffer) -> int: +def padShape(shape: Tuple[int, ...], rank: int) -> Tuple[int, ...]: + assert rank >= len( + shape), f"Cannot pad to rank smaller then shape's. Received rank: {rank}, shape rank: {len(shape)}" + ret = tuple([1] * (rank - len(shape))) + shape + assert len(ret) == rank + return ret - minimalRect, baselineRect = minimizeRectangleDims(hyperRectangle, referenceBuffer) - offsetMult = [1] - for dim in reversed(baselineRect.dims[1:]): - offsetMult.insert(0, dim * np.prod(offsetMult)) +def padOffset(offset: Tuple[int, ...], rank: int) -> Tuple[int, ...]: + assert rank >= len( + offset), f"Cannot pad to rank smaller then offset's. Received rank: {rank}, offset rank: {len(offset)}" + ret = tuple([0] * (rank - len(offset))) + offset + assert len(ret) == rank + return ret - accOffset = 0 - for offsetIdx, mult in zip(minimalRect.offset, offsetMult): - accOffset += offsetIdx * mult - return int(accOffset * (referenceBuffer._type.referencedType.typeWidth // 8)) +def padStride(stride: Tuple[int, ...], rank: int, paddingStride: int) -> Tuple[int, ...]: + assert rank >= len( + stride), f"Cannot pad to rank smaller then stride's. Received rank: {rank}, stride rank: {len(stride)}" + ret = tuple([paddingStride] * (rank - len(stride))) + stride + assert len(ret) == rank + return ret -def extractTilingTransfer(tilingSolution: NodeMemoryConstraint, targetMemLevel: str, - tensorName: str) -> Optional[MemoryTransfer]: +def stridesFromShape(shape: Sequence[int]) -> Tuple[int, ...]: + strides = [1] * len(shape) + for idx, dim in enumerate(reversed(shape[1:])): + strides[idx + 1] = strides[idx] * dim + return tuple(reversed(strides)) - for name, constraint in tilingSolution.tensorMemoryConstraints.items(): - if not name == tensorName: - continue - sourceIdx = 0 +def calculateFlatOffset(offsets: Sequence[int], strides: Sequence[int]) -> int: + assert len(offsets) == len(strides), \ + f"Offsets and strides have to have the same number of dimensions. Length offsets: {len(offsets)}, strides: {len(strides)}" + return sum(offset * stride for offset, stride in zip(offsets, strides)) - for idx, memConstraint in enumerate(constraint.memoryConstraints.values()): - if memConstraint.memoryLevel != targetMemLevel: - continue - sourceIdx = idx - targetIdx = idx - 1 +def calculateFlatOffsetInBytes(tile: HyperRectangle, referenceBuffer: VariableBuffer) -> int: + return int( + calculateFlatOffset(tile.offset, stridesFromShape(referenceBuffer.shape)) * + (referenceBuffer._type.referencedType.typeWidth // 8)) - if sourceIdx == 0: - return None - return MemoryTransfer( - list(constraint.memoryConstraints.values())[targetIdx], - list(constraint.memoryConstraints.values())[sourceIdx]) +def computeTileHyperRectangles(memoryTransfer: MemoryTransfer) -> List[HyperRectangle]: + assert memoryTransfer.source.shape is not None, "Source transfer shape cannot be undefined!" + assert memoryTransfer.destination.shape is not None, "Destination transfer shape cannot be undefined!" - raise RuntimeError(f"{tensorName} not found in tilingSolution!") + assert len(memoryTransfer.source.shape) == len(memoryTransfer.destination.shape), \ + f"Source and target of memory transfer {memoryTransfer} don't have the same number of dimensions!" + largeShape = memoryTransfer.source.shape + smallShape = memoryTransfer.destination.shape -def computeHyperRectangleList(memTrans: MemoryTransfer) -> List[HyperRectangle]: + for dimIdx, (dimSizeSmall, dimSizeLarge) in enumerate(zip(smallShape, largeShape)): + assert dimSizeSmall <= dimSizeLarge, f"smallShape[{dimIdx}] should not be bigger then largeShape[{dimIdx}]. ({dimSizeSmall} > {dimSizeLarge})" - def nextElement(idxVec: List[int], targetVector: List[int]) -> Optional[List[int]]: - nextIdx = [] - - countUp = True - for vecIdx, maxIdx in zip(reversed(idxVec), reversed(targetVector)): - if countUp: - if vecIdx == maxIdx: - nextIdx.append(1) + def nextTileIndex(tileIndexEnd: List[int]) -> Generator[List[int]]: + tileCount = np.prod(tileIndexEnd) + tileIndex = [0] * len(tileIndexEnd) + for _ in range(tileCount): + yield tileIndex + for dimIdx, (idx, end) in enumerate(zip(tileIndex, tileIndexEnd)): + if idx + 1 < end: + tileIndex[dimIdx] = idx + 1 + break else: - nextIdx.append(vecIdx + 1) - countUp = False - else: - nextIdx.append(vecIdx) - - nextIdx.reverse() - - if countUp: - return None - - return nextIdx - - def calculateCost(idxVec: Iterable[int], smallShape: Tuple[int]) -> List[int]: - outVec = [] - for idx, step in zip(idxVec, smallShape): - outVec.append((idx - 1) * step) - - return outVec - - def calculateDim(idxVec: List[int], numTiles: List[int], smallShape: Tuple[int], - largeShape: Tuple[int]) -> List[int]: - - dimVec = [] - - for idx, (vecIdx, maxIdx) in enumerate(zip(idxVec, numTiles)): - if vecIdx != maxIdx: - dimVec.append(smallShape[idx]) - continue - if largeShape[idx] % smallShape[idx] == 0: - dimVec.append(smallShape[idx]) - continue - dimVec.append(largeShape[idx] % smallShape[idx]) - - return dimVec - - src = memTrans.source - dst = memTrans.destination - - largeShape = src.shape - smallShape = dst.shape - - assert largeShape is not None, "Transfer shapes cannot be undefined!" - assert smallShape is not None, "Transfer shapes cannot be undefined!" - - assert len(smallShape) == len( - largeShape), f"Source and target of memory transfer {memTrans} don't have the same number of dimensions!" - for idx, (dim1, dim2) in enumerate(zip(smallShape, largeShape)): - assert dim1 <= dim2, f"Large shape is smaller in dimension {idx}" - - totNumTiles = 1 - numTiles: List[int] = [] + tileIndex[dimIdx] = 0 - for (dim1, dim2) in zip(smallShape, largeShape): - totNumTiles *= np.ceil(dim2 / dim1) - numTiles.append(int(np.ceil(dim2 / dim1))) + tileHyperRectangles = [] - cubeList: List[HyperRectangle] = [] - idxVec = [1] * len(smallShape) + tileIndexEnd = [ + int(np.ceil(dimSizeLarge / dimSizeSmall)) for dimSizeLarge, dimSizeSmall in zip(largeShape, smallShape) + ] + for tileIndex in nextTileIndex(tileIndexEnd): + tileOffset = tuple(dimIdx * dimSizeSmall for dimIdx, dimSizeSmall in zip(tileIndex, smallShape)) + for dimIdx, (dimOffset, dimSizeLarge) in enumerate(zip(tileOffset, largeShape)): + assert dimOffset >= 0, f"tileOffset[{dimIdx}] shoud not be smaller then zero ({dimOffset} < 0)" + assert dimOffset < dimSizeLarge, f"tileOffset[{dimIdx}] should not be bigger or equal then largeShape[{dimIdx}] ({dimOffset} >= {dimSizeLarge})" - for i in range(int(totNumTiles)): - offsetVec = calculateCost(idxVec, smallShape) - dimVec = calculateDim(idxVec, numTiles, smallShape, largeShape) - cubeList.append(HyperRectangle(tuple(offsetVec), tuple(dimVec))) + tileSize = tuple( + min(dimSizeSmall, dimSizeLarge - dimOffset) + for dimSizeSmall, dimSizeLarge, dimOffset in zip(smallShape, largeShape, tileOffset)) + for dimIdx, (dimSize, dimSizeSmall) in enumerate(zip(tileSize, smallShape)): + assert dimSize > 0, f"tileOffset[{dimIdx}] shoud not be smaller or equal then zero ({dimSize} <= 0)" + assert dimSize <= dimSizeSmall, f"tileSize[{dimIdx}] should not be bigger then smallShape[{dimIdx}] ({dimSize} > {dimSizeSmall})" - nextVec = nextElement(idxVec, numTiles) - if nextVec is None: - break - idxVec = nextVec + tileHyperRectangles.append(HyperRectangle(tileOffset, tileSize)) - return cubeList + return tileHyperRectangles diff --git a/DeeployTest/Platforms/Siracusa/src/deeploytest.c b/DeeployTest/Platforms/Siracusa/src/deeploytest.c index 9a0d8f39db..8ed6952c72 100644 --- a/DeeployTest/Platforms/Siracusa/src/deeploytest.c +++ b/DeeployTest/Platforms/Siracusa/src/deeploytest.c @@ -169,7 +169,8 @@ void main(void) { i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { OUTPUTTYPE expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; OUTPUTTYPE actual = ((OUTPUTTYPE *)compbuf)[i]; - OUTPUTTYPE diff = expected - actual; + int error = expected - actual; + OUTPUTTYPE diff = (OUTPUTTYPE)(error < 0 ? -error : error); if (diff) { tot_err += 1; diff --git a/DeeployTest/deeployStateEqualityTest.py b/DeeployTest/deeployStateEqualityTest.py index 297e52e65c..58dbc7dad4 100644 --- a/DeeployTest/deeployStateEqualityTest.py +++ b/DeeployTest/deeployStateEqualityTest.py @@ -32,7 +32,7 @@ import onnx import onnx_graphsurgeon as gs from testUtils.platformMapping import mapDeployer, mapPlatform, setupMemoryPlatform -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.DeeployTypes import NetworkContext, StructBuffer, VariableBuffer, _backendPostBindingFilename, \ _middlewarePreLoweringFilename @@ -79,7 +79,7 @@ platform, signProp = mapPlatform(args.platform) for index, num in enumerate(test_inputs): - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset diff --git a/DeeployTest/generateNetwork.py b/DeeployTest/generateNetwork.py index bf590f06b1..7e05260c35 100644 --- a/DeeployTest/generateNetwork.py +++ b/DeeployTest/generateNetwork.py @@ -31,12 +31,11 @@ import numpy as np import onnx import onnx_graphsurgeon as gs -from testUtils.codeGenerate import generateTestInputsHeader, generateTestNetworkHeader, \ - generateTestNetworkImplementation, generateTestOutputsHeader +from testUtils.codeGenerate import generateTestNetwork from testUtils.graphDebug import generateDebugConfig from testUtils.platformMapping import mapDeployer, mapPlatform from testUtils.testRunner import TestGeneratorArgumentParser -from testUtils.typeMapping import inferInputType, parseDataType +from testUtils.typeMapping import inferTypeAndOffset, parseDataType from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import IntegerDataTypes @@ -52,9 +51,6 @@ def generateNetwork(args): onnx_graph = onnx.load_model(f'{args.dir}/network.onnx') graph = gs.import_onnx(onnx_graph) - inputTypes = {} - inputOffsets = {} - inputs = np.load(f'{args.dir}/inputs.npz') outputs = np.load(f'{args.dir}/outputs.npz') if os.path.isfile(f'{args.dir}/activations.npz'): @@ -110,8 +106,11 @@ def generateNetwork(args): platform, signProp = mapPlatform(args.platform) - for index, (name, num) in enumerate(zip(inputs.files, test_inputs)): - if np.prod(num.shape) == 0: + inputTypes = {} + inputOffsets = {} + + for index, (name, values) in enumerate(zip(inputs.files, test_inputs)): + if np.prod(values.shape) == 0: continue if name in manual_keys: @@ -119,7 +118,7 @@ def generateNetwork(args): offset = manual_offsets[name] # Check if the provided values fit into the dereferenced type - vals = num.astype(np.int64) - offset + vals = values.astype(np.int64) - offset if not _type.checkPromotion(vals): lo, hi = _type.typeMin, _type.typeMax raise RuntimeError(f"Provided type '{_type.typeName}' with offset {offset} " @@ -135,7 +134,7 @@ def generateNetwork(args): _type = PointerClass(_type) else: - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(values, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset @@ -156,39 +155,36 @@ def generateNetwork(args): # Parse graph and infer output levels and signedness _ = deployer.generateFunction(verbose = verbosityCfg) - # Create input and output vectors - os.makedirs(f'{args.dumpdir}', exist_ok = True) - print("=" * 80) - testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets, verbose = args.verbose) - f = open(f'{args.dumpdir}/testinputs.h', "w") - f.write(testInputStr) - f.close() - - testOutputStr = generateTestOutputsHeader(deployer, test_outputs, signProp, verbose = args.verbose) - f = open(f'{args.dumpdir}/testoutputs.h', "w") - f.write(testOutputStr) - f.close() - - # Generate code for Network - testNetworkHeaderStr = generateTestNetworkHeader(deployer, platform) - f = open(f'{args.dumpdir}/Network.h', "w") - f.write(testNetworkHeaderStr) - f.close() - - testNetworkImplementationStr = generateTestNetworkImplementation(deployer, platform, verbose = args.verbose) - f = open(f'{args.dumpdir}/Network.c', "w") - f.write(testNetworkImplementationStr) - f.close() - - clang_format = "{BasedOnStyle: llvm, IndentWidth: 2, ColumnLimit: 160}" - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/Network.c') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/Network.h') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/testoutputs.h') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/testinputs.h') + # Offset the input and output values if signprop + if signProp: + test_inputs = [value - inputOffsets[f"input_{i}"] for i, value in enumerate(test_inputs)] + + for i, values in enumerate(test_outputs): + buffer = deployer.ctxt.lookup(f"output_{i}") + if buffer._type.referencedType.typeName == "float32_t": + continue + if not buffer._signed: + values -= buffer.nLevels // 2 + + generateTestNetwork(deployer, test_inputs, test_outputs, args.dumpdir, verbosityCfg) if args.verbose: print() print("=" * 80) + print("Output:") + for i in range(len(test_outputs)): + buffer = deployer.ctxt.lookup(f"output_{i}") + logLine = f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}" + if signProp: + logLine += f", nLevels: {buffer.nLevels}, Signed: {buffer._signed}" + print(logLine) + print('Input:') + for i in range(len(test_inputs)): + buffer = deployer.ctxt.lookup(f"input_{i}") + print( + f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}, Offset: {inputOffsets[buffer.name]}" + ) + print("=" * 80) num_ops = deployer.numberOfOps(args.verbose) print("=" * 80) print() diff --git a/DeeployTest/testDebugPrintPass.py b/DeeployTest/testDebugPrintPass.py index bbd7373f10..a3e05e39e0 100644 --- a/DeeployTest/testDebugPrintPass.py +++ b/DeeployTest/testDebugPrintPass.py @@ -31,7 +31,7 @@ import onnx_graphsurgeon as gs from testUtils.platformMapping import mapDeployer, mapPlatform from testUtils.testRunner import TestGeneratorArgumentParser, getPaths -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.DebugPasses import DebugPrintPass from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel @@ -71,10 +71,7 @@ test_inputs = [inputs[x].reshape(-1).astype(np.float64) for x in inputs.files] test_outputs = [outputs[x].reshape(-1).astype(np.float64) for x in outputs.files] for index, num in enumerate(test_inputs): - # WIESP: Do not infer types and offset of empty arrays - if np.prod(num.shape) == 0: - continue - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset diff --git a/DeeployTest/testDmas.py b/DeeployTest/testDmas.py new file mode 100644 index 0000000000..6cca30e15d --- /dev/null +++ b/DeeployTest/testDmas.py @@ -0,0 +1,68 @@ +import itertools +import subprocess +from typing import Tuple + + +def test(dma: str, inputShape: Tuple[int, ...], tileShape: Tuple[int, ...], nodeCount: int, dataType: str, + doublebuffer: bool): + cfg_str = f""" + - input shape: {inputShape} + - tile shape: {tileShape} + - node count: {nodeCount} + - data type: {dataType} + - doublebuffering: {doublebuffer} + - dma: {dma} + """ + + print(f"test{dma}: Testing {dma} with followig configuration:" + cfg_str) + + testRunnerMap = { + "MchanDma": "testRunner_siracusa_mchandma.py", + "L3Dma": "testRunner_siracusa_l3dma.py", + "SnitchDma": "testRunner_snitch_dma.py", + } + + assert dma in testRunnerMap, f"{dma} missing its own testRunner mapping" + + testRunner = testRunnerMap[dma] + + cmd = [f"python {testRunner}", f"-t test{dma}", "-DNUM_CORES=8"] + cmd.append(f"--input-shape {' '.join(str(x) for x in inputShape)}") + cmd.append(f"--tile-shape {' '.join(str(x) for x in tileShape)}") + cmd.append(f"--node-count {nodeCount}") + cmd.append(f"--type {dataType}") + if doublebuffer: + cmd.append("--doublebuffer") + + full_cmd = " ".join(cmd) + + print(f"Running command:\n{full_cmd}\n") + + try: + subprocess.run(full_cmd, shell = True, check = True) + except subprocess.CalledProcessError: + print(f"test{dma}: Failed test:" + cfg_str) + print(f"Rerun with command:\n{full_cmd}") + exit(-1) + + +# input shape, tile shape, node count, data type +test_shapes_and_more = [ + ((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"), +] + +is_doublebuffers = [True, False] +dmas = ["MchanDma", "L3Dma", "SnitchDma"] + +for testShape, doublebuffer, dma in itertools.product(test_shapes_and_more, is_doublebuffers, dmas): + inputShape, tileShape, nodeCount, dataType = testShape + test(dma, inputShape, tileShape, nodeCount, dataType, doublebuffer) diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index 6f0342e7b4..a50ff739ea 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -26,94 +26,30 @@ import os import sys from collections import OrderedDict -from typing import List, Union +from typing import List import numpy as np import onnx import onnx_graphsurgeon as gs import pytest -from ortools.constraint_solver.pywrapcp import IntVar -from testUtils.codeGenerate import generateL3HexDump, generateTestInputsHeader, generateTestNetworkHeader, \ - generateTestNetworkImplementation, generateTestOutputsHeader +from testUtils.codeGenerate import generateTestNetwork from testUtils.graphDebug import generateDebugConfig from testUtils.platformMapping import mapDeployer, mapPlatform, setupMemoryPlatform from testUtils.testRunner import TestGeneratorArgumentParser -from testUtils.typeMapping import inferInputType +from testUtils.tilingUtils import DBOnlyL3Tiler, DBTiler, SBTiler +from testUtils.typeMapping import inferTypeAndOffset -from Deeploy.DeeployTypes import CodeGenVerbosity, ConstantBuffer, NetworkContext, NetworkDeployer, ONNXLayer, \ - SubGraph, TransientBuffer +from Deeploy.DeeployTypes import CodeGenVerbosity, NetworkDeployer, ONNXLayer from Deeploy.EngineExtension.NetworkDeployers.EngineColoringDeployer import EngineColoringDeployerWrapper from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryDeployerWrapper from Deeploy.MemoryLevelExtension.OptimizationPasses.MemoryLevelAnnotationPasses import AnnotateDefaultMemoryLevel, \ AnnotateIOMemoryLevel, AnnotateNeurekaWeightMemoryLevel -from Deeploy.TilingExtension.TilerExtension import Tiler, TilerDeployerWrapper -from Deeploy.TilingExtension.TilerModel import TilerModel +from Deeploy.TilingExtension.TilerExtension import TilerDeployerWrapper _TEXT_ALIGN = 30 -class DBOnlyL3Tiler(Tiler): - - def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], - hop: str, tensorName: str) -> Union[int, IntVar]: - - varBuffer = ctxt.lookup(tensorName) - - generalCoeff = 2 - - if isinstance(varBuffer, TransientBuffer): - coefficient = 1 - elif isinstance(varBuffer, ConstantBuffer): - coefficient = generalCoeff - else: - coefficient = generalCoeff - - if args.defaultMemLevel == "L2": - return coefficient - - if hop == 'L1': - return 1 - - return coefficient - - -class DBTiler(Tiler): - - def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], - hop: str, tensorName: str) -> Union[int, IntVar]: - varBuffer = ctxt.lookup(tensorName) - - generalCoeff = 2 - - if isinstance(varBuffer, TransientBuffer): - coefficient = 1 - elif isinstance(varBuffer, ConstantBuffer): - coefficient = generalCoeff - else: - coefficient = generalCoeff - - return coefficient - - -class SBTiler(Tiler): - - def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], - hop: str, tensorName: str) -> Union[int, IntVar]: - varBuffer = ctxt.lookup(tensorName) - - generalCoeff = 1 - - if isinstance(varBuffer, TransientBuffer): - coefficient = 1 - elif isinstance(varBuffer, ConstantBuffer): - coefficient = generalCoeff - else: - coefficient = generalCoeff - - return coefficient - - # Mock of the Global Scheduler's inteface # Returns a list of list of nodes instead of simply a list # Inner list represent the patter over which we tile @@ -161,10 +97,7 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg platform.engines[0].enableStrides = True for index, num in enumerate(test_inputs): - # WIESP: Do not infer types and offset of empty arrays - if np.prod(num.shape) == 0: - continue - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset @@ -198,7 +131,11 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg # Make the deployer tiler aware if args.doublebuffer: - deployer = TilerDeployerWrapper(deployer, DBOnlyL3Tiler) + assert args.defaultMemLevel in ["L3", "L2"] + if args.defaultMemLevel == "L3": + deployer = TilerDeployerWrapper(deployer, DBOnlyL3Tiler) + else: + deployer = TilerDeployerWrapper(deployer, DBTiler) else: deployer = TilerDeployerWrapper(deployer, SBTiler) @@ -336,10 +273,7 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg signProp = False for index, num in enumerate(test_inputs): - # WIESP: Do not infer types and offset of empty arrays - if np.prod(num.shape) == 0: - continue - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset @@ -355,42 +289,36 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg _ = deployer.generateFunction(verbosityCfg) - # Create input and output vectors - os.makedirs(f'{args.dumpdir}', exist_ok = True) - - print("=" * 80) - testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets, args.verbose) - f = open(f'{args.dumpdir}/testinputs.h', "w") - f.write(testInputStr) - f.close() - - testOutputStr = generateTestOutputsHeader(deployer, test_outputs, signProp, args.verbose) - f = open(f'{args.dumpdir}/testoutputs.h', "w") - f.write(testOutputStr) - f.close() + # Offset the input and output values if signprop + if signProp: + test_inputs = [value - inputOffsets[f"input_{i}"] for i, value in enumerate(test_inputs)] - # Generate code for Network - testNetworkHeaderStr = generateTestNetworkHeader(deployer, platform) - f = open(f'{args.dumpdir}/Network.h', "w") - f.write(testNetworkHeaderStr) - f.close() + for i, values in enumerate(test_outputs): + buffer = deployer.ctxt.lookup(f"output_{i}") + if buffer._type.referencedType.typeName == "float32_t": + continue + if not buffer._signed: + values -= buffer.nLevels // 2 - testNetworkImplementationStr = generateTestNetworkImplementation(deployer, platform) - f = open(f'{args.dumpdir}/Network.c', "w") - f.write(testNetworkImplementationStr) - f.close() - - generateL3HexDump(deployer, os.path.join(f'{args.dumpdir}', 'hex'), test_inputs, test_outputs) - - clang_format = "{BasedOnStyle: llvm, IndentWidth: 2, ColumnLimit: 160}" - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/Network.c') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/Network.h') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/testoutputs.h') - os.system(f'clang-format -i --style="{clang_format}" {args.dumpdir}/testinputs.h') + generateTestNetwork(deployer, test_inputs, test_outputs, args.dumpdir, verbosityCfg) if args.verbose: print() print("=" * 80) + print("Output:") + for i in range(len(test_outputs)): + buffer = deployer.ctxt.lookup(f"output_{i}") + logLine = f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}" + if signProp: + logLine += f", nLevels: {buffer.nLevels}, Signed: {buffer._signed}" + print(logLine) + print('Input:') + for i in range(len(test_inputs)): + buffer = deployer.ctxt.lookup(f"input_{i}") + print( + f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}, Offset: {inputOffsets[buffer.name]}" + ) + print("=" * 80) num_ops = deployer.numberOfOps(args.verbose) print("=" * 80) print() diff --git a/DeeployTest/testMemoryLevelExtension.py b/DeeployTest/testMemoryLevelExtension.py index 5532f5c010..22a5405a5c 100644 --- a/DeeployTest/testMemoryLevelExtension.py +++ b/DeeployTest/testMemoryLevelExtension.py @@ -32,7 +32,7 @@ import onnx_graphsurgeon as gs from testUtils.platformMapping import defaultScheduler, mapDeployer, mapPlatform, setupMemoryPlatform from testUtils.testRunner import TestGeneratorArgumentParser, getPaths -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ NCHWtoNHWCPass, TransposeMatmulInputsPass @@ -87,7 +87,7 @@ platform, signProp = mapPlatform(args.platform) for index, num in enumerate(test_inputs): - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset if "simpleRegression" in args.dir: diff --git a/DeeployTest/testPrintInputOutputTransformation.py b/DeeployTest/testPrintInputOutputTransformation.py index 3b2d6d144d..1bf4f90c54 100644 --- a/DeeployTest/testPrintInputOutputTransformation.py +++ b/DeeployTest/testPrintInputOutputTransformation.py @@ -31,7 +31,7 @@ import onnx_graphsurgeon as gs from testUtils.platformMapping import mapDeployer, mapPlatform from testUtils.testRunner import TestGeneratorArgumentParser, getPaths -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.CommonExtensions.CodeTransformationPasses.PrintInputs import MemoryAwarePrintInputGeneration, \ MemoryAwarePrintOutputGeneration, PrintInputGeneration, PrintOutputGeneration @@ -89,10 +89,7 @@ test_inputs = [inputs[x].reshape(-1).astype(np.float64) for x in inputs.files] test_outputs = [outputs[x].reshape(-1).astype(np.float64) for x in outputs.files] for index, num in enumerate(test_inputs): - # WIESP: Do not infer types and offset of empty arrays - if np.prod(num.shape) == 0: - continue - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset diff --git a/DeeployTest/testRunner_siracusa_l3dma.py b/DeeployTest/testRunner_siracusa_l3dma.py new file mode 100644 index 0000000000..7507bf8ec9 --- /dev/null +++ b/DeeployTest/testRunner_siracusa_l3dma.py @@ -0,0 +1,94 @@ +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 new file mode 100644 index 0000000000..c16f584b21 --- /dev/null +++ b/DeeployTest/testRunner_siracusa_mchandma.py @@ -0,0 +1,95 @@ +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_dma.py b/DeeployTest/testRunner_snitch_dma.py new file mode 100644 index 0000000000..96e6542bb9 --- /dev/null +++ b/DeeployTest/testRunner_snitch_dma.py @@ -0,0 +1,100 @@ +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/testSchedulingExtension.py b/DeeployTest/testSchedulingExtension.py index d6372def22..bd339b93dd 100644 --- a/DeeployTest/testSchedulingExtension.py +++ b/DeeployTest/testSchedulingExtension.py @@ -33,7 +33,7 @@ import pytest from testUtils.platformMapping import mapDeployer, mapPlatform, setupMemoryPlatform from testUtils.testRunner import TestGeneratorArgumentParser -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.DeeployTypes import NetworkContext, NetworkDeployer, ONNXLayer, Schedule, StructBuffer, TransientBuffer, \ VariableBuffer @@ -249,7 +249,7 @@ def setupDeployer(memoryHierarchy: MemoryHierarchy, graph: gs.Graph) -> NetworkD platform, signProp = mapPlatform(args.platform) for index, num in enumerate(test_inputs): - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset diff --git a/DeeployTest/testSlice_PULP.py b/DeeployTest/testSlice_PULP.py index dda9d13a58..35052381ee 100644 --- a/DeeployTest/testSlice_PULP.py +++ b/DeeployTest/testSlice_PULP.py @@ -30,12 +30,12 @@ import numpy as np import onnx import onnx_graphsurgeon as gs -from testUtils.codeGenerate import generateTestInputsHeader, generateTestNetworkHeader, \ - generateTestNetworkImplementation, generateTestOutputsHeader +from testUtils.codeGenerate import generateTestNetwork from testUtils.platformMapping import mapDeployer, setupMemoryPlatform from testUtils.testRunner import escapeAnsi -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset +from Deeploy.DeeployTypes import _NoVerbosity from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryDeployerWrapper from Deeploy.Targets.PULPOpen.Platform import PULPPlatform @@ -86,7 +86,7 @@ platform = PULPPlatform() for index, num in enumerate(test_inputs): - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset @@ -100,9 +100,9 @@ deployer.frontEnd() deployer.parse(deployer.default_channels_first) - deployer.ctxt.lookup('onnx::Slice_5')._memoryLevel = "L1" - deployer.ctxt.lookup('onnx::Slice_5').allocTemplate = pulpL1AllocateTemplate - deployer.ctxt.lookup('onnx::Slice_5').deallocTemplate = pulpL1FreeTemplate + deployer.ctxt.lookup('onnxSlice_5_tensor')._memoryLevel = "L1" + deployer.ctxt.lookup('onnxSlice_5_tensor').allocTemplate = pulpL1AllocateTemplate + deployer.ctxt.lookup('onnxSlice_5_tensor').deallocTemplate = pulpL1FreeTemplate deployer.midEnd() @@ -110,35 +110,17 @@ deployer.prepared = True deployer.generateInferenceCode() - # Create input and output vectors - os.makedirs('TEST_SIRACUSA/Tests/testSlice', exist_ok = True) - - testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets) - f = open('TEST_SIRACUSA/Tests/testSlice/testinputs.h', "w") - f.write(testInputStr) - f.close() - - testOutputStr = generateTestOutputsHeader(deployer, test_outputs, signProp, False) - f = open('TEST_SIRACUSA/Tests/testSlice/testoutputs.h', "w") - f.write(testOutputStr) - f.close() - - # Generate code for Network - testNetworkHeaderStr = generateTestNetworkHeader(deployer, platform) - f = open('TEST_SIRACUSA/Tests/testSlice/Network.h', "w") - f.write(testNetworkHeaderStr) - f.close() - - testNetworkImplementationStr = generateTestNetworkImplementation(deployer, platform) - f = open('TEST_SIRACUSA/Tests/testSlice/Network.c', "w") - f.write(testNetworkImplementationStr) - f.close() - - clang_format = "{BasedOnStyle: llvm, IndentWidth: 2, ColumnLimit: 160}" - os.system(f'clang-format -i --style="{clang_format}" TEST_SIRACUSA/Tests/testSlice/Network.c') - os.system(f'clang-format -i --style="{clang_format}" TEST_SIRACUSA/Tests/testSlice/Network.h') - os.system(f'clang-format -i --style="{clang_format}" TEST_SIRACUSA/Tests/testSlice/testoutputs.h') - os.system(f'clang-format -i --style="{clang_format}" TEST_SIRACUSA/Tests/testSlice/testinputs.h') + # Offset the values if signprop + if signProp: + test_inputs = [value - inputOffsets[f"input_{i}"] for i, value in enumerate(test_inputs)] + + for i, values in enumerate(test_outputs): + buffer = deployer.ctxt.lookup(f"output_{i}") + isFloat = buffer._type.referencedType.typeName == "float32_t" + if not isFloat and not buffer._signed: + values -= buffer.nLevels // 2 + + generateTestNetwork(deployer, test_inputs, test_outputs, 'TEST_SIRACUSA/Tests/testSlice', _NoVerbosity) os.system( f"$CMAKE -DTOOLCHAIN={args.toolchain} -DTOOLCHAIN_INSTALL_DIR={_TOOLCHAIN_DIR} -DTESTNAME=testSlice -DGENERATED_SOURCE=TEST_SIRACUSA/Tests/testSlice -Dplatform=Siracusa -B TEST_SIRACUSA/build -DNUM_CORES=1 .." diff --git a/DeeployTest/testTilerExtension.py b/DeeployTest/testTilerExtension.py index edf1e6d1cc..6ee23b40fc 100644 --- a/DeeployTest/testTilerExtension.py +++ b/DeeployTest/testTilerExtension.py @@ -33,7 +33,7 @@ import pytest from testUtils.platformMapping import mapDeployer, mapPlatform, setupMemoryPlatform from testUtils.testRunner import TestGeneratorArgumentParser -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferTypeAndOffset from Deeploy.DeeployTypes import GlobalDefinition, NetworkDeployer, ONNXLayer, Schedule, TransientBuffer from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel @@ -165,7 +165,7 @@ def setupDeployer(memoryHierarchy: MemoryHierarchy, graph: gs.Graph) -> NetworkD platform, signProp = mapPlatform(args.platform) for index, num in enumerate(test_inputs): - _type, offset = inferInputType(num, signProp)[0] + _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset if "simpleRegression" in args.dir: diff --git a/DeeployTest/testUtils/codeGenerate.py b/DeeployTest/testUtils/codeGenerate.py index 5e572643a4..eb148ad2be 100644 --- a/DeeployTest/testUtils/codeGenerate.py +++ b/DeeployTest/testUtils/codeGenerate.py @@ -24,11 +24,11 @@ # limitations under the License. import os -from typing import Dict, List, Optional, Tuple +from typing import List, Tuple import numpy as np -from Deeploy.DeeployTypes import ConstantBuffer, DeploymentPlatform, NetworkDeployer, VariableBuffer +from Deeploy.DeeployTypes import CodeGenVerbosity, ConstantBuffer, NetworkDeployer, VariableBuffer from Deeploy.Targets.MemPool.Platform import MemPoolPlatform _TEXT_ALIGN = 30 @@ -50,115 +50,78 @@ def _shapeBroadcast(ctxt, value, name): return broadcastNum -def generateTestInputsHeader(deployer: NetworkDeployer, - test_inputs: List, - inputTypes: Dict, - inputOffsets: Dict, - verbose: Optional[bool] = None) -> str: +def generateTestInputsHeader(deployer: NetworkDeployer, test_inputs: List) -> str: + vectors = [] retStr = "" - inputNames = [deployer.ctxt.lookup(buf.name) for buf in deployer.graph.inputs] - inputTypes = {buf.name: buf._type for buf in inputNames} - - for index, num in enumerate(test_inputs): - - if f"input_{index}" not in inputTypes.keys(): + for index, values in enumerate(test_inputs): + # WIESEP: Correctly handle empty arrays + if np.prod(values.shape) == 0: continue - # WIESEP: Correctly handle empty arrays - if np.prod(num.shape) == 0: + bufferName = f"input_{index}" + + #LMACAN: We have some tests which have extra inputs and this is a hack to circumvent that + if not deployer.ctxt.is_buffer(bufferName): continue - test_inputs[index] -= inputOffsets[f"input_{index}"] + values = _shapeBroadcast(deployer.ctxt, values, bufferName) - broadcastNum = _shapeBroadcast(deployer.ctxt, num, f"input_{index}") + buffer = deployer.ctxt.lookup(bufferName) + typeName = buffer._type.referencedType.typeName + typeWidth = buffer._type.referencedType.typeWidth - data_type = inputTypes[f"input_{index}"] - data_width = inputTypes[f"input_{index}"].referencedType.typeWidth + vectorName = f"testInputVector{index}" + vectors.append(vectorName) - retStr += f"{data_type.referencedType.typeName} testInputVector{index}[] =" + retStr += f"{typeName} {vectorName}[] =" retStr += "{" - if data_type.referencedType.typeName == 'float32_t': - list_str = (", ").join([f'{x}f' if not (np.isinf(x) or np.isnan(x)) else str(x) for x in broadcastNum]) + if typeName == 'float32_t': + list_str = (", ").join([f'{x}f' if not (np.isinf(x) or np.isnan(x)) else str(x) for x in values]) else: - list_str = (", ").join([str(x) for x in broadcastNum]) + list_str = (", ").join([str(x) for x in values]) - # WIESEP: Arrays have to be 4 byte alinged (at lest in banshee) - bytes = len(broadcastNum) * (data_width // 8) + # WIESEP: Arrays have to be 4 byte aligned (at least in banshee) + bytes = (len(values) * typeWidth) // 8 if bytes % 4 != 0: - bytes = 4 * int((bytes / 4 + 1)) - padding = (bytes * 8) // data_width - len(broadcastNum) + paddingBytes = bytes % 4 + paddingElements = paddingBytes * 8 // typeWidth list_str += ", " - list_str += (", ").join([str(0) for x in range(padding)]) + list_str += (", ").join([str(0) for _ in range(paddingElements)]) retStr += list_str retStr += "};\n" - retStr += f"void* testInputVector[{len(inputTypes)}] = " + "{" - retStr += ", ".join([ - f"testInputVector{idx}" for idx, _ in enumerate(test_inputs) - if np.prod(test_inputs[idx].shape) != 0 and f"input_{idx}" in inputTypes.keys() - ]) + retStr += f"void* testInputVector[{len(vectors)}] = {{" + retStr += ", ".join(vectors) retStr += "};\n" - - if verbose: - print('Input:') - for name in inputTypes.keys(): - buf = deployer.ctxt.lookup(name) - print(f" - '{name}': Type: {buf._type.referencedType.typeName}, Offset: {inputOffsets[name]}") - return retStr -def generateTestOutputsHeader(deployer: NetworkDeployer, - test_outputs: List, - signProp: Optional[bool] = None, - verbose: Optional[bool] = None) -> str: - - output_signed = {} - output_n_levels = {} - output_data_type = {} - - if signProp is None: - signProp = False - - if verbose is None: - verbose = False - +def generateTestOutputsHeader(deployer: NetworkDeployer, test_outputs: List[np.ndarray]) -> str: retStr = "" + for index, values in enumerate(test_outputs): + typeName = deployer.ctxt.lookup(f'output_{index}')._type.referencedType.typeName + typeWidth = deployer.ctxt.lookup(f'output_{index}')._type.referencedType.typeWidth - for index, num in enumerate(test_outputs): - output_data_type[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}')._type - - data_type = output_data_type[f"output_{index}"] - isdatafloat = (data_type.referencedType.typeName == "float32_t") - - output_n_levels[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}').nLevels - output_signed[f"output_{index}"] = deployer.ctxt.lookup(f'output_{index}')._signed - if signProp and not isdatafloat: - test_outputs[index] -= int( - ((1 - output_signed[f"output_{index}"]) * (output_n_levels[f"output_{index}"] / 2))) - - data_width = data_type.referencedType.typeWidth - retStr += f"#define OUTPUTTYPE {data_type.referencedType.typeName}\n" - if isdatafloat: - retStr += f"#define ISOUTPUTFLOAT 1\n" - else: - retStr += f"#define ISOUTPUTFLOAT 0\n" - retStr += f"{data_type.referencedType.typeName} testOutputVector{index}[] =" + retStr += f"#define OUTPUTTYPE {typeName}\n" + retStr += f"#define ISOUTPUTFLOAT {int(typeName == 'float32_t')}\n" + retStr += f"{typeName} testOutputVector{index}[] =" retStr += "{" - # WIESEP: Arrays have to be 4 byte alinged (at lest in banshee) - if data_type.referencedType.typeName == 'float32_t': - list_str = (", ").join([f'{x}f' if not (np.isinf(x) or np.isnan(x)) else str(x) for x in num]) + values = values.flatten() + + if typeName == "float32_t": + list_str = (", ").join([f'{x}f' if not (np.isinf(x) or np.isnan(x)) else str(x) for x in values]) else: - list_str = (", ").join([str(x) for x in num]) + list_str = (", ").join([str(x) for x in values]) - bytes = len(num) * (data_width // 8) + # WIESEP: Arrays have to be 4 byte aligned (at least in banshee) + bytes = (len(values) * typeWidth) // 8 if bytes % 4 != 0: - bytes = 4 * int((bytes / 4 + 1)) - padding = (bytes * 8) // data_width - len(num) + paddingBytes = bytes % 4 + paddingElements = paddingBytes * 8 // typeWidth list_str += ", " - list_str += (", ").join([str(0) for x in range(padding)]) + list_str += (", ").join([str(0) for _ in range(paddingElements)]) retStr += list_str retStr += "};\n" @@ -166,27 +129,16 @@ def generateTestOutputsHeader(deployer: NetworkDeployer, retStr += f"void* testOutputVector[{len(test_outputs)}] = " + "{" retStr += ", ".join([f"testOutputVector{idx}" for idx, _ in enumerate(test_outputs)]) retStr += "};\n" - - if verbose: - print('Output:') - if signProp: - for (name, buf), (_, n_level), (_, signed) in zip(output_data_type.items(), output_n_levels.items(), - output_signed.items()): - print(f" - '{name}': Type: {buf.referencedType.typeName}, nLevels: {n_level}, Signed: {signed}") - else: - for (name, buf) in output_data_type.items(): - print(f" - '{name}': Type: {buf.referencedType.typeName}") - return retStr -def generateTestNetworkHeader(deployer: NetworkDeployer, platform: DeploymentPlatform) -> str: +def generateTestNetworkHeader(deployer: NetworkDeployer) -> str: retStr = "" retStr += """ - #ifndef __DEEPLOY_HEADER_ - #define __DEEPLOY_HEADER_ + #ifndef __DEEPLOY_HEADER__ + #define __DEEPLOY_HEADER__ #include #include #include @@ -206,13 +158,7 @@ def generateTestNetworkHeader(deployer: NetworkDeployer, platform: DeploymentPla return retStr -def generateTestNetworkImplementation(deployer: NetworkDeployer, - platform: DeploymentPlatform, - verbose: Optional[bool] = None) -> str: - - if verbose is None: - verbose = False - +def generateTestNetworkImplementation(deployer: NetworkDeployer, verbosityCfg: CodeGenVerbosity) -> str: retStr = "" retStr += """#include @@ -230,7 +176,7 @@ def generateTestNetworkImplementation(deployer: NetworkDeployer, retStr += deployer.generateGlobalDefinitionCode() # WIESEP: Mempool assigns section attributes to intermediate buffers to allow . - if isinstance(platform, MemPoolPlatform): + if isinstance(deployer.Platform, MemPoolPlatform): retStr += deployer.generateInferenceInitializationCode() retStr += """ void RunNetwork(__attribute__((unused)) uint32_t core_id, __attribute__((unused)) uint32_t numThreads){ @@ -241,7 +187,7 @@ def generateTestNetworkImplementation(deployer: NetworkDeployer, """ retStr += deployer.generateInferenceInitializationCode() - retStr += deployer.generateFunction(verbose) + retStr += deployer.generateFunction(verbosityCfg) retStr += """ } @@ -308,3 +254,36 @@ def dumpBuffer(buf: VariableBuffer, path: str): if hasattr(buf, "extName"): pathName = os.path.join(path, f"{buf.extName}.hex") dumpBuffer(buf, pathName) + + +def generateTestNetwork(deployer: NetworkDeployer, test_inputs: List[np.ndarray], test_outputs: List[np.ndarray], + dumpdir: str, verbosityCfg: CodeGenVerbosity) -> None: + assert deployer.prepared, "An unprepared deployer was given" + + # Create input and output vectors + os.makedirs(dumpdir, exist_ok = True) + + testInputStr = generateTestInputsHeader(deployer, test_inputs) + with open(f'{dumpdir}/testinputs.h', "w") as f: + f.write(testInputStr) + + testOutputStr = generateTestOutputsHeader(deployer, test_outputs) + with open(f'{dumpdir}/testoutputs.h', "w") as f: + f.write(testOutputStr) + + # Generate code for Network + testNetworkHeaderStr = generateTestNetworkHeader(deployer) + with open(f'{dumpdir}/Network.h', "w") as f: + f.write(testNetworkHeaderStr) + + testNetworkImplementationStr = generateTestNetworkImplementation(deployer, verbosityCfg) + with open(f'{dumpdir}/Network.c', "w") as f: + f.write(testNetworkImplementationStr) + + generateL3HexDump(deployer, os.path.join(f'{dumpdir}', 'hex'), test_inputs, test_outputs) + + clang_format = "{BasedOnStyle: llvm, IndentWidth: 2, ColumnLimit: 160}" + os.system(f'clang-format -i --style="{clang_format}" {dumpdir}/Network.c') + os.system(f'clang-format -i --style="{clang_format}" {dumpdir}/Network.h') + os.system(f'clang-format -i --style="{clang_format}" {dumpdir}/testoutputs.h') + os.system(f'clang-format -i --style="{clang_format}" {dumpdir}/testinputs.h') diff --git a/DeeployTest/testUtils/dmaUtils.py b/DeeployTest/testUtils/dmaUtils.py new file mode 100644 index 0000000000..f9722168d6 --- /dev/null +++ b/DeeployTest/testUtils/dmaUtils.py @@ -0,0 +1,373 @@ +import math +from typing import Dict, List, Optional, Tuple, Type + +import numpy.typing as npt +import onnx_graphsurgeon as gs + +from Deeploy.AbstractDataTypes import BaseType, Pointer, PointerClass +from Deeploy.CommonExtensions.DataTypes import minimalIntegerType +from Deeploy.DeeployTypes import NetworkContext, NetworkDeployer, NodeParser, NodeTemplate, NodeTypeChecker, \ + ONNXLayer, OperatorRepresentation, VariableBuffer +from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel +from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryDeployerWrapper, \ + MemoryPlatformWrapper +from Deeploy.MemoryLevelExtension.OptimizationPasses.MemoryLevelAnnotationPasses import AnnotateDefaultMemoryLevel, \ + AnnotateIOMemoryLevel +from Deeploy.Targets.PULPOpen.Deployer import PULPDeployer +from Deeploy.Targets.PULPOpen.Platform import MemoryPULPPlatform, PULPOptimizer +from Deeploy.Targets.Snitch.Deployer import SnitchDeployer +from Deeploy.Targets.Snitch.Platform import SnitchOptimizer, SnitchPlatform +from Deeploy.TilingExtension.MemoryConstraints import MemoryConstraint, NodeMemoryConstraint, \ + PatternMemoryConstraints, TensorMemoryConstraint +from Deeploy.TilingExtension.MemoryScheduler import MemoryBlock +from Deeploy.TilingExtension.TileConstraint import TileConstraint +from Deeploy.TilingExtension.TilerExtension import MemoryMap, TilerDeployerWrapper, TilingSolution +from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, TilingSchedule, VariableReplacementScheme + +from .tilingUtils import DBOnlyL3Tiler, DBTiler, SBTiler + +memcpyTemplate = NodeTemplate(""" +memcpy((void *)${dest}, (void *)${src}, ${size}); +""") + + +# Same interface as NodeTypeChecker but allow any input type and the +# output type matches the input type. +class MemcpyTypeChecker(NodeTypeChecker): + + def __init__(self): + super().__init__([], []) + + def typeInferOutput(self, ctxt: NetworkContext, node: gs.Node, + operatorRepresentation: OperatorRepresentation) -> NetworkContext: + assert len(node.inputs) == 1 and len(node.outputs) == 1 + buffer_in = ctxt.lookup(node.inputs[0].name) + ctxt.annotateType(node.outputs[0].name, buffer_in._type) + return ctxt + + def typeCheckNodeInputs(self, ctxt: NetworkContext, node: gs.Node) -> bool: + return True + + def typeInferGlobalCtxt(self, ctxt: NetworkContext, node: gs.Node) -> NetworkContext: + # Whatever it has already annotated, it's good + return ctxt + + +class MemcpyTileConstraint(TileConstraint): + + @classmethod + def serializeTilingSolution( + cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], + targetMemLevel: str, ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: + inputLoadSchedule = [{"src": absCube.rectangle} for absCube in absoluteOutputCubes] + outputLoadSchedule = [{"dest": absCube.rectangle} for absCube in absoluteOutputCubes] + inputOffsets, outputOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, + ["src", "dest"]) + + def size(abs: AbsoluteHyperRectangle, buffer: VariableBuffer) -> int: + return math.prod(abs.rectangle.dims) * (buffer._type.referencedType.typeWidth // 8) + + buffer_src = ctxt.lookup(operatorRepresentation['src']) + assert isinstance(buffer_src, VariableBuffer) + + replacements: Dict[str, List[int]] = {"size": [size(abs, buffer_src) for abs in absoluteOutputCubes]} + replacement_types = {key: PointerClass(minimalIntegerType(values)) for key, values in replacements.items()} + + return VariableReplacementScheme(replacements, + replacement_types), TilingSchedule(inputOffsets, outputOffsets, + inputLoadSchedule, outputLoadSchedule) + + +class MemcpyParser(NodeParser): + + def parseNode(self, node: gs.Node) -> bool: + return len(node.inputs) == 1 and len(node.outputs) == 1 + + def parseNodeCtxt(self, + ctxt: NetworkContext, + node: gs.Node, + channels_first: bool = True) -> Tuple[NetworkContext, bool]: + assert len(node.inputs) == 1 and len(node.outputs) == 1 + src = ctxt.lookup(node.inputs[0].name) + self.operatorRepresentation['src'] = src.name + self.operatorRepresentation['dest'] = ctxt.lookup(node.outputs[0].name).name + self.operatorRepresentation['size'] = math.prod(src.shape) * (src._type.referencedType.typeWidth // 8) + return ctxt, True + + +class MemcpyLayer(ONNXLayer): + pass + + +def generate_graph(nodeCount: int, shape: Tuple[int, ...], dtype: npt.DTypeLike) -> gs.Graph: + assert nodeCount > 0 + + tensor_in = gs.Variable(name = "input_0", dtype = dtype, shape = shape) + + nodes = [] + for i in range(nodeCount): + tensor_out = gs.Variable(name = f"out_{i}", dtype = dtype, shape = shape) + nodes.append(gs.Node("Memcpy", f"memcpy_{i}", {}, [tensor_in], [tensor_out])) + tensor_in = tensor_out + + return gs.Graph(nodes, [nodes[0].inputs[0]], [nodes[-1].outputs[0]], "dma_test_graph") + + +def generate_tiling(ctxt: NetworkContext, memoryStart: str, memoryOrder: List[str], memoryHierarchy: MemoryHierarchy, + inputShape: Tuple[int, ...], tileShape: Tuple[int, ...], graph: gs.Graph, _type: BaseType, + doublebuffer: bool) -> Tuple[TilingSolution, MemoryMap]: + assert memoryStart in memoryOrder + memoryStartIndex = memoryOrder.index(memoryStart) + + if memoryStartIndex + 1 < len(memoryOrder): + memoryMultibuffer = memoryOrder[memoryOrder.index(memoryStart) + 1] + else: + memoryMultibuffer = None + + if memoryStartIndex + 2 < len(memoryOrder): + singleTileMemories = memoryOrder[memoryStartIndex + 2:] + else: + singleTileMemories = [] + + inputSize = math.prod(inputShape) + tileSize = math.prod(tileShape) + + def assertFitsInMemory(size: int, memory: str) -> None: + memorySize = memoryHierarchy.memoryLevels[memory].size + assert size <= memorySize, f"The required tensor space is too big for the {memory} memory. Required space: {size}, memory space: {memorySize}" + + inputSizeInBytes = inputSize * (_type.typeWidth // 8) + assertFitsInMemory(2 * inputSizeInBytes, memoryStart) + + tileSizeInBytes = tileSize * (_type.typeWidth // 8) + for memory in singleTileMemories: + assertFitsInMemory(2 * tileSizeInBytes, memory) + + if doublebuffer: + multiBufferCoefficient = 2 + else: + multiBufferCoefficient = 1 + + multibufferSizeInBytes = tileSizeInBytes * multiBufferCoefficient + if memoryMultibuffer is not None: + assertFitsInMemory(multibufferSizeInBytes + tileSizeInBytes, memoryMultibuffer) + + inputMultibufferAddrSpace = (0, multibufferSizeInBytes) + outputMultibufferAddrSpace = (multibufferSizeInBytes, 2 * multibufferSizeInBytes) + + inputTileAddrSpace = (0, tileSizeInBytes) + outputTileAddrSpace = (tileSizeInBytes, 2 * tileSizeInBytes) + + # Tiling Solution + + tilingSolution = [] + + def generateMemoryConstraint(memory: str, shape: Tuple[int, ...], multiBufferCoefficient: int, + addrSpace: Optional[Tuple[int, int]]) -> MemoryConstraint: + size = math.prod(shape) + mc = MemoryConstraint(memory, size) + mc.shape = shape + mc.multiBufferCoefficient = multiBufferCoefficient + if addrSpace is not None: + mc.addrSpace = addrSpace + return mc + + for node in graph.nodes: + inputMemoryConstraints = {} + outputMemoryConstraints = {} + for i, memory in enumerate(memoryOrder[memoryOrder.index(memoryStart):]): + if i == 0: + inputMc = generateMemoryConstraint(memory = memory, + shape = inputShape, + multiBufferCoefficient = 1, + addrSpace = None) + outputMc = generateMemoryConstraint(memory = memory, + shape = inputShape, + multiBufferCoefficient = 1, + addrSpace = None) + elif i == 1: + inputMc = generateMemoryConstraint(memory = memory, + shape = tileShape, + multiBufferCoefficient = multiBufferCoefficient, + addrSpace = inputMultibufferAddrSpace) + outputMc = generateMemoryConstraint(memory = memory, + shape = tileShape, + multiBufferCoefficient = multiBufferCoefficient, + addrSpace = outputMultibufferAddrSpace) + else: + inputMc = generateMemoryConstraint(memory = memory, + shape = tileShape, + multiBufferCoefficient = 1, + addrSpace = inputTileAddrSpace) + outputMc = generateMemoryConstraint(memory = memory, + shape = tileShape, + multiBufferCoefficient = 1, + addrSpace = outputTileAddrSpace) + inputMemoryConstraints[memory] = inputMc + outputMemoryConstraints[memory] = outputMc + + inputTensorMemoryConstraint = TensorMemoryConstraint(tensorName = node.inputs[0].name, + constraints = inputMemoryConstraints, + ctxt = ctxt) + + outputTensorMemoryConstraint = TensorMemoryConstraint(tensorName = node.outputs[0].name, + constraints = outputMemoryConstraints, + ctxt = ctxt) + + nodeMemoryConstraint = NodeMemoryConstraint() + nodeMemoryConstraint.addTensorConstraint(inputTensorMemoryConstraint, 'input') + nodeMemoryConstraint.addTensorConstraint(outputTensorMemoryConstraint, 'output') + + patternMemoryConstraints = PatternMemoryConstraints() + patternMemoryConstraints.addConstraint(nodeMemoryConstraint) + + tilingSolution.append(patternMemoryConstraints) + + # Memory Map + + # Initialize an empty memory map + memoryMap = {memory: [[] for _ in range(len(graph.nodes) + 1)] for memory in memoryOrder} + + # Set memoryStart memory + + def appendMemoryMapStart(tensorName: str, lifetime: Tuple[int, int], addrSpace: Tuple[int, int]) -> None: + memoryMap[memoryStart][-1].append(MemoryBlock(tensorName, memoryStart, lifetime, addrSpace)) + + addrSpacePing = (0, inputSizeInBytes) + addrSpacePong = (inputSizeInBytes, 2 * inputSizeInBytes) + + ## First input tensor has a special lifetime (0, 0) + appendMemoryMapStart(graph.nodes[0].inputs[0].name, (0, 0), addrSpacePing) + + for i, node in enumerate(graph.nodes): + # Start with addrSpacePong because we used "Ping" for the first input tensor + appendMemoryMapStart(node.outputs[0].name, (i, i + 1), addrSpacePong if i % 2 == 0 else addrSpacePing) + + ## Set the rest + + def setMemoryMapRest(memory: str, inputAddrSpace: Tuple[int, int], outputAddrSpace: Tuple[int, int]) -> None: + for i, node in enumerate(graph.nodes): + # Empirically concluded from looking at produced memory maps + if i + 1 == len(graph.nodes): + endLifetime = i + 1 + else: + endLifetime = i + + memoryMap[memory][i].extend([ + MemoryBlock(name = node.inputs[0].name, level = memory, lifetime = (i, i), addrSpace = inputAddrSpace), + MemoryBlock(name = node.outputs[0].name, + level = memory, + lifetime = (i, endLifetime), + addrSpace = outputAddrSpace), + ]) + + if memoryMultibuffer is not None: + setMemoryMapRest(memoryMultibuffer, inputMultibufferAddrSpace, outputMultibufferAddrSpace) + + for memory in singleTileMemories: + setMemoryMapRest(memory, inputTileAddrSpace, outputTileAddrSpace) + + return tilingSolution, memoryMap + + +def defaultScheduler(graph: gs.Graph) -> List[List[gs.Node]]: + return [[node] for node in graph.nodes] + + +def setup_pulp_deployer(defaultMemory: str, targetMemory: str, graph: gs.Graph, inputTypes: Dict[str, Type[Pointer]], + doublebuffer: bool, deeployStateDir: str) -> NetworkDeployer: + L3 = MemoryLevel(name = "L3", neighbourNames = ["L2"], size = 64000000) + L2 = MemoryLevel(name = "L2", neighbourNames = ["L3", "L1"], size = 1024000) + L1 = MemoryLevel(name = "L1", neighbourNames = ["L2"], size = 64000) + memoryLevels = [L3, L2, L1] + memoryLevelMap = {mem.name: mem for mem in memoryLevels} + + assert defaultMemory in memoryLevelMap, f"defaultMemory {defaultMemory} is not part of PULP's memory hierarchy {list(memoryLevelMap.keys())}" + assert targetMemory in memoryLevelMap, f"targetMemory {targetMemory} is not part of PULP's memory hierarchy {list(memoryLevelMap.keys())}" + + memoryHierarchy = MemoryHierarchy(memoryLevels) + memoryHierarchy.setDefaultMemoryLevel(defaultMemory) + + platform = MemoryPULPPlatform(memoryHierarchy, memoryLevelMap[targetMemory]) + + deployer = PULPDeployer(graph, + platform, + inputTypes, + PULPOptimizer, + defaultScheduler, + default_channels_first = True, + deeployStateDir = deeployStateDir) + + memoryLevelAnnotationPasses = [AnnotateIOMemoryLevel(defaultMemory), AnnotateDefaultMemoryLevel(memoryHierarchy)] + # Make the deployer memory-level aware + deployer = MemoryDeployerWrapper(deployer, memoryLevelAnnotationPasses) + + if doublebuffer: + assert defaultMemory in ["L3", "L2"] + if defaultMemory == "L3": + deployer = TilerDeployerWrapper(deployer, DBOnlyL3Tiler) + else: + deployer = TilerDeployerWrapper(deployer, DBTiler) + else: + deployer = TilerDeployerWrapper(deployer, SBTiler) + + return deployer + + +def setup_snitch_deployer(defaultMemory: str, targetMemory: str, graph: gs.Graph, inputTypes: Dict[str, Type[Pointer]], + doublebuffer: bool, deeployStateDir: str) -> NetworkDeployer: + L3 = MemoryLevel(name = "L3", neighbourNames = ["L2"], size = 64000000) + L2 = MemoryLevel(name = "L2", neighbourNames = ["L3", "L1"], size = 1024000) + L1 = MemoryLevel(name = "L1", neighbourNames = ["L2"], size = 64000) + memoryLevels = [L3, L2, L1] + memoryLevelMap = {mem.name: mem for mem in memoryLevels} + + assert defaultMemory in memoryLevelMap, f"defaultMemory {defaultMemory} is not part of PULP's memory hierarchy {list(memoryLevelMap.keys())}" + assert targetMemory in memoryLevelMap, f"targetMemory {targetMemory} is not part of PULP's memory hierarchy {list(memoryLevelMap.keys())}" + + memoryHierarchy = MemoryHierarchy(memoryLevels) + memoryHierarchy.setDefaultMemoryLevel(defaultMemory) + + platform = SnitchPlatform() + platform = MemoryPlatformWrapper(platform, memoryHierarchy, memoryLevelMap[targetMemory]) + + deployer = SnitchDeployer(graph, + platform, + inputTypes, + SnitchOptimizer, + defaultScheduler, + deeployStateDir = deeployStateDir) + memoryLevelAnnotationPasses = [AnnotateIOMemoryLevel(defaultMemory), AnnotateDefaultMemoryLevel(memoryHierarchy)] + # Make the deployer memory-level aware + deployer = MemoryDeployerWrapper(deployer, memoryLevelAnnotationPasses) + + assert defaultMemory == "L2" + if doublebuffer: + deployer = TilerDeployerWrapper(deployer, DBTiler) + else: + deployer = TilerDeployerWrapper(deployer, SBTiler) + + return deployer + + +def prepare_deployer_with_custom_tiling(deployer: NetworkDeployer, defaultMemory: str, targetMemory: str, + tileShape: Tuple[int, ...], doublebuffer: bool) -> None: + # Decomposed deployer.prepare() to enter a custom tiling solution + deployer.frontEnd() + super(TilerDeployerWrapper, deployer).bind() + + tilingSolution, memoryMap = generate_tiling( + ctxt = deployer.ctxt, + memoryStart = defaultMemory, + memoryOrder = [defaultMemory, targetMemory], + memoryHierarchy = deployer.Platform.memoryHierarchy, + inputShape = deployer.graph.inputs[0].shape, + tileShape = tileShape, + graph = deployer.graph, + _type = deployer.inputTypes['input_0'].referencedType, + doublebuffer = doublebuffer, + ) + deployer.tile(tilingSolution, memoryMap) + deployer.backEnd() + deployer.prepared = True diff --git a/DeeployTest/testUtils/platformMapping.py b/DeeployTest/testUtils/platformMapping.py index 3e9639a688..56cd3d7d28 100644 --- a/DeeployTest/testUtils/platformMapping.py +++ b/DeeployTest/testUtils/platformMapping.py @@ -23,10 +23,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, Dict, Optional, Tuple, Union +from typing import Callable, Dict, Optional, Tuple, Type, Union import onnx_graphsurgeon as gs +from Deeploy.AbstractDataTypes import Pointer from Deeploy.DeeployTypes import DeploymentPlatform, NetworkDeployer, TopologyOptimizer from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryPlatform, MemoryPlatformWrapper @@ -111,7 +112,7 @@ def setupMemoryPlatform(platform: DeploymentPlatform, memoryHierarchy: MemoryHie def mapDeployer(platform: DeploymentPlatform, graph: gs.Graph, - inputTypes: Dict[str, type], + inputTypes: Dict[str, Type[Pointer]], loweringOptimizer: Optional[TopologyOptimizer] = None, scheduler: Optional[Callable] = None, name: Optional[str] = None, diff --git a/DeeployTest/testUtils/testRunner.py b/DeeployTest/testUtils/testRunner.py index a3dc6a7189..353856c2ca 100644 --- a/DeeployTest/testUtils/testRunner.py +++ b/DeeployTest/testUtils/testRunner.py @@ -322,6 +322,7 @@ def __init__(self, self.gen_args = gen_args self._dir_gen_root = f'TEST_{platform.upper()}' + assert self._args.toolchain_install_dir is not None, f"Environment variable LLVM_INSTALL_DIR is not set" self._dir_toolchain = os.path.normpath(self._args.toolchain_install_dir) self._dir_build = f"{self._dir_gen_root}/build" self._dir_gen, self._dir_test, self._name_test = getPaths(self._args.dir, self._dir_gen_root) diff --git a/DeeployTest/testUtils/tilingUtils.py b/DeeployTest/testUtils/tilingUtils.py new file mode 100644 index 0000000000..78a9bbcdd8 --- /dev/null +++ b/DeeployTest/testUtils/tilingUtils.py @@ -0,0 +1,41 @@ +from typing import List, Union + +from ortools.constraint_solver.pywrapcp import IntVar + +from Deeploy.DeeployTypes import NetworkContext, SubGraph, TransientBuffer +from Deeploy.TilingExtension.TilerExtension import Tiler +from Deeploy.TilingExtension.TilerModel import TilerModel + + +class DBOnlyL3Tiler(Tiler): + + def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], + hop: str, tensorName: str) -> Union[int, IntVar]: + buffer = ctxt.lookup(tensorName) + + if isinstance(buffer, TransientBuffer): + return 1 + + if hop == 'L1': + return 1 + + return 2 + + +class DBTiler(Tiler): + + def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], + hop: str, tensorName: str) -> Union[int, IntVar]: + buffer = ctxt.lookup(tensorName) + + if isinstance(buffer, TransientBuffer): + return 1 + + return 2 + + +class SBTiler(Tiler): + + def multiBufferStrategy(self, tilerModel: TilerModel, ctxt: NetworkContext, pattern: SubGraph, path: List[str], + hop: str, tensorName: str) -> Union[int, IntVar]: + return 1 diff --git a/DeeployTest/testUtils/typeMapping.py b/DeeployTest/testUtils/typeMapping.py index a551b25150..15242c93ea 100644 --- a/DeeployTest/testUtils/typeMapping.py +++ b/DeeployTest/testUtils/typeMapping.py @@ -23,15 +23,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -from collections import namedtuple -from typing import List +from typing import Tuple, Type import numpy as np +import numpy.typing as npt -from Deeploy.AbstractDataTypes import PointerClass -from Deeploy.CommonExtensions.DataTypes import FloatDataTypes, IntegerDataTypes, int8_t - -offsetType = namedtuple("offsetType", ("type", "offset")) +from Deeploy.AbstractDataTypes import BaseType, IntegerImmediate, Pointer, PointerClass +from Deeploy.CommonExtensions.DataTypes import FloatDataTypes, IntegerDataTypes, float32_t, int8_t, int16_t, int32_t, \ + minimalFloatType, minimalIntegerType, uint8_t, uint16_t, uint32_t _ALL_DTYPES: dict[str, type] = {t.typeName: t for t in (*IntegerDataTypes, *FloatDataTypes)} @@ -60,34 +59,36 @@ def parseDataType(name: str) -> type: return _ALL_DTYPES[name] -def isInteger(_input: np.array) -> bool: - if np.abs((_input.astype(int) - _input)).max() > 0.001: - return False - return True +def isInteger(x: npt.NDArray) -> bool: + return np.abs((x.astype(int) - x)).max() <= 0.001 + + +def inferMinimalType(values: np.ndarray, default: Type[BaseType] = int8_t) -> Type[BaseType]: + # WIESEP: We cannot do type inference for empty arrays. + if np.prod(values.shape) == 0: + print(f"Warning: Empty input array for type inference for {values}!") + return default + + if isInteger(values): + return minimalIntegerType(values) + else: + return minimalFloatType(values) -def isUnsigned(_input: np.array) -> bool: - if (_input).min() < 0: - return False - return True +def signPropTypeAndOffset(_type: Type[IntegerImmediate]) -> Tuple[Type[IntegerImmediate], int]: + if _type.signed: + return _type, 0 + unsigned2signed = { + unsigned.typeName: signed for unsigned, signed in zip([t for t in IntegerDataTypes if t.typeMin == 0 + ], [t for t in IntegerDataTypes if t.typeMin < 0]) + } -def dataWidth(n): - count = 0 - n = np.abs(int(n - 1)) - while (n > 0): - count += 1 - n = n >> 8 - ret = 2**(count + 2) - if ret < 8: - ret = 8 - return ret + signedType = unsigned2signed[_type.typeName] + return signedType, 2**(signedType.typeWidth - 1) -def inferInputType(values: np.ndarray, - signProp: bool = False, - defaultType = int8_t, - defaultOffset = 0) -> List[offsetType]: +def inferTypeAndOffset(values: np.ndarray, signProp: bool = False) -> Tuple[Type[Pointer], int]: """Infers the data type of the provided input array. Parameters @@ -97,50 +98,55 @@ def inferInputType(values: np.ndarray, signProp : bool Whether to consider signedness when inferring the data type. - - defaultType : type - The default data type to use if inference fails. - - defaultOffset : int - The default offset to use if inference fails. - Returns ------- - List[offsetType] - A list of inferred data types and their corresponding offsets. + Tuple[Type[BaseType], int] + The inferred type and offset """ - # WIESEP: We cannot do type inference for empty arrays. - if np.prod(values.shape) == 0: - print(f"Warning: Empty input array for type inference for {values}!") - return [(defaultType, defaultOffset)] - - signedPlatformTypes = [_type for _type in IntegerDataTypes if _type.typeMin < 0] - - matchingTypes = [] - - # There is implicit knowledge encoded in the order of the checks (i.e. first unsigned, signed - # and then float). - if signProp and isUnsigned(values) and isInteger(values): - for _type in sorted(signedPlatformTypes, key = lambda x: x.typeWidth): - signPropOffset = (2**(_type.typeWidth - 1)) - if _type.checkPromotion(values - signPropOffset): - matchingTypes.append(offsetType(PointerClass(_type), signPropOffset)) - elif isInteger(values): - sorted_types = sorted( - IntegerDataTypes, - key = lambda t: (t.typeWidth, t.typeMin < 0), - ) - - for _type in sorted_types: - if _type.checkPromotion(values): - matchingTypes.append(offsetType(PointerClass(_type), 0)) - else: - for _type in sorted(FloatDataTypes, key = lambda x: x.typeWidth): - if _type.checkPromotion(values): - matchingTypes.append(offsetType(PointerClass(_type), 0)) + _type = inferMinimalType(values) - if not matchingTypes: - raise RuntimeError("Could not find a matching type!") - - return matchingTypes + if signProp and issubclass(_type, IntegerImmediate): + _type, offset = signPropTypeAndOffset(_type) + else: + offset = 0 + + return PointerClass(_type), offset + + +def baseTypeFromName(name: str) -> Type[BaseType]: + if name == "int8_t": + return int8_t + elif name == "uint8_t": + return uint8_t + elif name == "int16_t": + return int16_t + elif name == "uint16_t": + return uint16_t + elif name == "int32_t": + return int32_t + elif name == "uint32_t": + return uint32_t + elif name == "float32_t": + return float32_t + else: + raise RuntimeError(f"Unrecognized name {name}") + + +def dtypeFromDeeployType(_ty: Type[BaseType]) -> npt.DTypeLike: + if _ty == int8_t: + return np.int8 + elif _ty == uint8_t: + return np.uint8 + elif _ty == int16_t: + return np.int16 + elif _ty == uint16_t: + return np.uint16 + elif _ty == int32_t: + return np.int32 + elif _ty == uint32_t: + return np.uint32 + elif _ty == float32_t: + return np.float32 + else: + raise RuntimeError(f"Unimplemented conversion for type {_ty.typeName}") diff --git a/TargetLibraries/PULPOpen/CMakeLists.txt b/TargetLibraries/PULPOpen/CMakeLists.txt index 30bc9aa094..bf67dfca01 100644 --- a/TargetLibraries/PULPOpen/CMakeLists.txt +++ b/TargetLibraries/PULPOpen/CMakeLists.txt @@ -3,7 +3,7 @@ file(GLOB_RECURSE SOURCES ) if(NOT DEFINED ENV{PULP_SDK_HOME}) - message(FATAL_ERROR "Environemnt variable PULP_SDK_HOME not set.") + message(FATAL_ERROR "Environment variable PULP_SDK_HOME not set.") endif() if(platform STREQUAL "Siracusa" OR platform STREQUAL "Siracusa_w_neureka") diff --git a/TargetLibraries/PULPOpen/inc/dory_dma.h b/TargetLibraries/PULPOpen/inc/dory_dma.h deleted file mode 100644 index 9b2c4259ab..0000000000 --- a/TargetLibraries/PULPOpen/inc/dory_dma.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * dory.h - * Alessio Burrello - * - * Copyright (C) 2019-2020 University of Bologna - * - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _DORY_DMA_H -#define _DORY_DMA_H - -typedef struct { - void *ext; - void *loc; - unsigned short hwc_to_chw; - unsigned short stride_2d; - unsigned short number_of_2d_copies; - unsigned short stride_1d; - unsigned short number_of_1d_copies; - unsigned int length_1d_copy; - unsigned int mchan_cmd; - int dir; // 0 l1->l2, 1 l2->l1 - int tid; -} DMA_copy; - -void dory_dma_memcpy_hwc_to_chw(DMA_copy *copy); - -void dory_dma_memcpy_1d_async(DMA_copy *copy); - -void dory_dma_memcpy_2d_async(DMA_copy *copy); - -void dory_dma_memcpy_3d_async(DMA_copy *copy); - -void dory_dma_memcpy_async(DMA_copy *copy); - -void dory_dma_free(DMA_copy *copy); - -void dory_dma_barrier(DMA_copy *copy); - -int dory_dma_allocate(); -#endif diff --git a/TargetLibraries/PULPOpen/inc/mchan.h b/TargetLibraries/PULPOpen/inc/mchan.h deleted file mode 100644 index cd7c2ee799..0000000000 --- a/TargetLibraries/PULPOpen/inc/mchan.h +++ /dev/null @@ -1,161 +0,0 @@ -/* ===================================================================== - * Title: mchan.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - * Adopted from PULP-SDK (https://github.com/pulp-platform/pulp-sdk), released - under Apache 2.0 - - */ - -#ifndef _MCHAN_H -#define _MCHAN_H - -// Requires to have MCHAN_BASE_ADDR, MCHAN_EVENT defined outside of header -#ifndef MCHAN_BASE_ADDR -#error "[mchan.h] MCHAN_BASE_ADDR not defined!" -#endif - -#if !defined(MCHAN_EVENT) && !defined(MCHAN_POLLED) -#error "[mchan.h] Nor MCHAN_EVENT nor MCHAN_POLLED defined!" -#endif - -#if defined(MCHAN_EVENT) && !defined(MCHAN_EVENT_BIT) -#error \ - "[mchan.h] MCHAN_EVENT_BIT should be defined when using events as signalization!" -#endif - -#include "pmsis.h" - -#define MCHAN_CMD_OFFSET 0 -#define MCHAN_STATUS_OFFSET 4 - -#define MCHAN_CMD_ADDR (MCHAN_BASE_ADDR + MCHAN_CMD_OFFSET) -#define MCHAN_STATUS_ADDR (MCHAN_BASE_ADDR + MCHAN_STATUS_OFFSET) - -#define READ_REG(addr) (*(volatile int *)(addr)) -#define WRITE_REG(addr, value) \ - do { \ - *(volatile int *)(addr) = (int)value; \ - } while (0) - -#define MCHAN_READ_CMD() READ_REG(MCHAN_CMD_ADDR) -#define MCHAN_WRITE_CMD(value) WRITE_REG(MCHAN_CMD_ADDR, value) - -#define MCHAN_READ_STATUS() READ_REG(MCHAN_STATUS_ADDR) -#define MCHAN_WRITE_STATUS(value) WRITE_REG(MCHAN_STATUS_ADDR, value) - -// MCHAN version 7 has 1 more bit for the transfer length, so all the flag -// offsets are shifted by 1. Also, LOC (TCDM) striding is not supported in v6. -#if MCHAN_VERSION == 7 -#define MCHAN_TRANSFER_LEN_SIZE (17) -#else -#define MCHAN_TRANSFER_LEN_SIZE (16) -#endif - -#define MCHAN_CMD_FLAG_DIRECTION_LOC2EXT (0 << (MCHAN_TRANSFER_LEN_SIZE + 0)) -#define MCHAN_CMD_FLAG_DIRECTION_EXT2LOC (1 << (MCHAN_TRANSFER_LEN_SIZE + 0)) -#define MCHAN_CMD_FLAG_INCREMENTAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 1)) -#define MCHAN_CMD_FLAG_2D_TRANSFER_EXTERNAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 2)) -#define MCHAN_CMD_FLAG_EVENT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 3)) -#define MCHAN_CMD_FLAG_INTERRUPT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 4)) -#define MCHAN_CMD_FLAG_BROADCAST_FINISH (1 << (MCHAN_TRANSFER_LEN_SIZE + 5)) -#if MCHAN_VERSION == 7 -#define MCHAN_CMD_FLAG_2D_TRANSFER_LOCAL \ - (1 << (MCHAN_TRANSFER_LEN_SIZE + 6)) // can only be used with MCHAN v7 -#endif -#define MCHAN_CMD_SHIFT_DIRECTION MCHAN_TRANSFER_LEN_SIZE - -#define MCHAN_CMD(len, dir, inc, loc_2d, ext_2d, int_en, event_en, broadcast) \ - (len | dir | inc | loc_2d | ext_2d | broadcast | int_en | event_en) - -typedef enum { - MCHAN_DMA_TRANSFER_DIRECTION_EXT2LOC = MCHAN_CMD_FLAG_DIRECTION_EXT2LOC, - MCHAN_DMA_TRANSFER_DIRECTION_LOC2EXT = MCHAN_CMD_FLAG_DIRECTION_LOC2EXT -} mchan_dma_transfer_direction_e; - -typedef struct { - int cmd; - int size; - - void *loc; - int loc_size_1d; - int loc_stride_1d; - - void *ext; - int ext_size_1d; - int ext_stride_1d; -} mchan_transfer_t; - -static int mchan_transfer_get_id() { return MCHAN_READ_CMD(); } - -static void mchan_transfer_push_1d(mchan_transfer_t trans) { - MCHAN_WRITE_CMD(trans.cmd); - MCHAN_WRITE_CMD(trans.loc); - MCHAN_WRITE_CMD(trans.ext); -} - -static void mchan_transfer_push_2d(mchan_transfer_t trans) { - MCHAN_WRITE_CMD(trans.cmd); - MCHAN_WRITE_CMD(trans.loc); - MCHAN_WRITE_CMD(trans.ext); -// MCHAN version 7 takes 2D "count" (length of 1D transfers) and stride in 2 -// steps, v7 takes it in 1 step with the stride shifted to the upper 16 bits. -#if MCHAN_VERSION == 7 - MCHAN_WRITE_CMD(trans.ext_size_1d); - MCHAN_WRITE_CMD(trans.ext_stride_1d); -#else - MCHAN_WRITE_CMD(trans.ext_size_1d | (trans.ext_stride_1d << 16)); -#endif -} - -static void mchan_transfer_push(mchan_transfer_t trans) { - MCHAN_WRITE_CMD(trans.cmd); - MCHAN_WRITE_CMD(trans.loc); - MCHAN_WRITE_CMD(trans.ext); - - if (trans.ext_size_1d < trans.size) { - MCHAN_WRITE_CMD(trans.ext_size_1d); - MCHAN_WRITE_CMD(trans.ext_stride_1d); - } - - if (trans.loc_size_1d < trans.size) { - MCHAN_WRITE_CMD(trans.loc_size_1d); - MCHAN_WRITE_CMD(trans.loc_stride_1d); - } -} - -static void mchan_transfer_free(int tid) { MCHAN_WRITE_STATUS(1 << tid); } - -static int mchan_transfer_busy(int tid) { - return MCHAN_READ_STATUS() & (1 << tid); -} - -static void mchan_transfer_wait(int tid) { -#if defined(MCHAN_EVENT) - while (mchan_transfer_busy(tid)) - eu_evt_maskWaitAndClr(1 << MCHAN_EVENT_BIT); -#elif defined(MCHAN_POLLED) - while (mchan_transfer_busy(tid)) - ; -#endif -} - -#endif diff --git a/TargetLibraries/PULPOpen/inc/mchan_siracusa.h b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h new file mode 100644 index 0000000000..2d44d7b29e --- /dev/null +++ b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h @@ -0,0 +1,15 @@ +// Default mchan base address +#ifndef MCHAN_BASE_ADDR +#define MCHAN_BASE_ADDR (ARCHI_MCHAN_DEMUX_ADDR) // CLUSTER_MCHAN_ADDR +#endif + +// Default mchan await mode +#if !defined(MCHAN_EVENT) && !defined(MCHAN_POLLED) +#define MCHAN_EVENT +#endif + +#ifdef MCHAN_EVENT +#define MCHAN_EVENT_BIT (ARCHI_CL_EVT_DMA0) // 8 +#endif + +#include "mchan_v7.h" diff --git a/TargetLibraries/PULPOpen/inc/mchan_v6.h b/TargetLibraries/PULPOpen/inc/mchan_v6.h new file mode 100644 index 0000000000..ffd4045519 --- /dev/null +++ b/TargetLibraries/PULPOpen/inc/mchan_v6.h @@ -0,0 +1,112 @@ +/* ===================================================================== + * Title: mchan_v6.h + * Description: + * + * $Date: 26.07.2024 + * + * ===================================================================== */ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + * Adopted from PULP-SDK (https://github.com/pulp-platform/pulp-sdk), released + under Apache 2.0 + + */ + +#ifndef __MCHAN_V6_H__ +#define __MCHAN_V6_H__ + +// Requires to have MCHAN_BASE_ADDR, MCHAN_EVENT defined outside of header +#ifndef MCHAN_BASE_ADDR +#error "[mchan_v6.h] MCHAN_BASE_ADDR not defined!" +#endif + +#if !defined(MCHAN_EVENT) && !defined(MCHAN_POLLED) +#error "[mchan_v6.h] Nor MCHAN_EVENT nor MCHAN_POLLED defined!" +#endif + +#if defined(MCHAN_EVENT) && defined(MCHAN_POLLED) +#error "[mchan_v6.h] Define either MCHAN_EVENT or MCHAN_POLLED, not both!" +#endif + +#if defined(MCHAN_EVENT) && !defined(MCHAN_EVENT_BIT) +#error \ + "[mchan_v6.h] MCHAN_EVENT_BIT should be defined when using events as signalization!" +#endif + +#if !defined(MCHAN_VERSION) +#define MCHAN_VERSION 6 +#elif MCHAN_VERSION != 6 +#error "[mchan_v6.h] Illegal MCHAN_VERSION. Supported only 6" +#endif + +#include "pmsis.h" + +#define MCHAN_TRANSFER_LEN_SIZE (16) + +#define MCHAN_CMD_FLAG_DIRECTION_LOC2EXT (0 << (MCHAN_TRANSFER_LEN_SIZE + 0)) +#define MCHAN_CMD_FLAG_DIRECTION_EXT2LOC (1 << (MCHAN_TRANSFER_LEN_SIZE + 0)) +#define MCHAN_CMD_FLAG_INCREMENTAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 1)) +#define MCHAN_CMD_FLAG_2D_TRANSFER_EXTERNAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 2)) +#define MCHAN_CMD_FLAG_EVENT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 3)) +#define MCHAN_CMD_FLAG_INTERRUPT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 4)) +#define MCHAN_CMD_FLAG_BROADCAST_FINISH (1 << (MCHAN_TRANSFER_LEN_SIZE + 5)) + +static volatile uint32_t *const cmd_ptr = + (volatile uint32_t *const)(MCHAN_BASE_ADDR + 0x0); +static volatile uint32_t *const status_ptr = + (volatile uint32_t *const)(MCHAN_BASE_ADDR + 0x4); + +static void mchan_transfer_1d(uint32_t cmd, void *loc, void *ext) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; +} + +static void mchan_transfer_2d_ext_strided(uint32_t cmd, void *loc, void *ext, + uint16_t ext_size_1d, + uint16_t ext_stride_2d) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; + *cmd_ptr = (uint32_t)ext_size_1d | ((uint32_t)ext_stride_2d << 16); +} + +static uint32_t mchan_channel_alloc() { return *cmd_ptr; } + +static void mchan_channel_free(uint32_t channel_id) { + // TODO: assert channel_id is smaller then 32 + *status_ptr = 1 << channel_id; +} + +static uint32_t mchan_channel_is_busy(uint32_t channel_id) { + // TODO: assert channel_id is smaller then 32 + return *status_ptr & (1 << channel_id); +} + +static void mchan_channel_wait(uint32_t channel_id) { + // TODO: assert channel_id is smaller then 32 +#if defined(MCHAN_EVENT) + while (mchan_channel_is_busy(channel_id)) + eu_evt_maskWaitAndClr(1 << MCHAN_EVENT_BIT); +#elif defined(MCHAN_POLLED) + while (mchan_channel_is_busy(channel_id)) + ; +#endif +} + +#endif // __MCHAN_V6_H__ diff --git a/TargetLibraries/PULPOpen/inc/mchan_v7.h b/TargetLibraries/PULPOpen/inc/mchan_v7.h new file mode 100644 index 0000000000..8f14a0efdc --- /dev/null +++ b/TargetLibraries/PULPOpen/inc/mchan_v7.h @@ -0,0 +1,138 @@ +/* ===================================================================== + * Title: mchan_v7.h + * Description: + * + * $Date: 26.07.2024 + * + * ===================================================================== */ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + + * Adopted from PULP-SDK (https://github.com/pulp-platform/pulp-sdk), released + under Apache 2.0 + + */ + +#ifndef __MCHAN_V7_H__ +#define __MCHAN_V7_H__ + +// Requires to have MCHAN_BASE_ADDR, MCHAN_EVENT defined outside of header +#ifndef MCHAN_BASE_ADDR +#error "[mchan_v7.h] MCHAN_BASE_ADDR not defined!" +#endif + +#if !defined(MCHAN_EVENT) && !defined(MCHAN_POLLED) +#error "[mchan_v7.h] Nor MCHAN_EVENT nor MCHAN_POLLED defined!" +#endif + +#if defined(MCHAN_EVENT) && defined(MCHAN_POLLED) +#error "[mchan_v7.h] Define either MCHAN_EVENT or MCHAN_POLLED, not both!" +#endif + +#if defined(MCHAN_EVENT) && !defined(MCHAN_EVENT_BIT) +#error \ + "[mchan_v7.h] MCHAN_EVENT_BIT should be defined when using events as signalization!" +#endif + +#if !defined(MCHAN_VERSION) +#define MCHAN_VERSION 7 +#elif MCHAN_VERSION != 7 +#error "[mchan_v7.h] Illegal MCHAN_VERSION. Supported only 7" +#endif + +#include "pmsis.h" + +#define MCHAN_TRANSFER_LEN_SIZE (17) + +#define MCHAN_CMD_FLAG_DIRECTION_LOC2EXT (0 << (MCHAN_TRANSFER_LEN_SIZE + 0)) +#define MCHAN_CMD_FLAG_DIRECTION_EXT2LOC (1 << (MCHAN_TRANSFER_LEN_SIZE + 0)) +#define MCHAN_CMD_FLAG_INCREMENTAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 1)) +#define MCHAN_CMD_FLAG_2D_TRANSFER_EXTERNAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 2)) +#define MCHAN_CMD_FLAG_EVENT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 3)) +#define MCHAN_CMD_FLAG_INTERRUPT_ENABLE (1 << (MCHAN_TRANSFER_LEN_SIZE + 4)) +#define MCHAN_CMD_FLAG_BROADCAST_FINISH (1 << (MCHAN_TRANSFER_LEN_SIZE + 5)) +#define MCHAN_CMD_FLAG_2D_TRANSFER_LOCAL (1 << (MCHAN_TRANSFER_LEN_SIZE + 6)) + +static volatile uint32_t *const cmd_ptr = + (volatile uint32_t *const)(MCHAN_BASE_ADDR + 0x0); +static volatile uint32_t *const status_ptr = + (volatile uint32_t *const)(MCHAN_BASE_ADDR + 0x4); + +static void mchan_transfer_1d(uint32_t cmd, void *loc, void *ext) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; +} + +static void mchan_transfer_2d_loc_strided(uint32_t cmd, void *loc, void *ext, + uint32_t loc_size_1d, + uint32_t loc_stride_2d) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; + *cmd_ptr = (uint32_t)loc_size_1d; + *cmd_ptr = (uint32_t)loc_stride_2d; +} + +static void mchan_transfer_2d_ext_strided(uint32_t cmd, void *loc, void *ext, + uint32_t ext_size_1d, + uint32_t ext_stride_2d) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; + *cmd_ptr = (uint32_t)ext_size_1d; + *cmd_ptr = (uint32_t)ext_stride_2d; +} + +static void mchan_transfer_2d_loc_strided_ext_strided( + uint32_t cmd, void *loc, void *ext, uint32_t loc_size_1d, + uint32_t loc_stride_2d, uint32_t ext_size_1d, uint32_t ext_stride_2d) { + // TODO: assert flags are set correctly + *cmd_ptr = (uint32_t)cmd; + *cmd_ptr = (uint32_t)loc; + *cmd_ptr = (uint32_t)ext; + *cmd_ptr = (uint32_t)ext_size_1d; + *cmd_ptr = (uint32_t)ext_stride_2d; + *cmd_ptr = (uint32_t)loc_size_1d; + *cmd_ptr = (uint32_t)loc_stride_2d; +} + +static uint32_t mchan_channel_alloc() { return *cmd_ptr; } + +static void mchan_channel_free(uint32_t channel_id) { + // TODO: assert tid is smaller then 32 + *status_ptr = 1 << channel_id; +} + +static uint32_t mchan_channel_is_busy(uint32_t channel_id) { + // TODO: assert tid is smaller then 32 + return *status_ptr & (1 << channel_id); +} + +static void mchan_channel_wait(uint32_t channel_id) { + // TODO: assert tid is smaller then 32 +#if defined(MCHAN_EVENT) + while (mchan_channel_is_busy(channel_id)) + eu_evt_maskWaitAndClr(1 << MCHAN_EVENT_BIT); +#elif defined(MCHAN_POLLED) + while (mchan_channel_is_busy(channel_id)) + ; +#endif +} + +#endif // __MCHAN_V7_H__ diff --git a/TargetLibraries/PULPOpen/src/dory_dma.c b/TargetLibraries/PULPOpen/src/dory_dma.c deleted file mode 100644 index 0aa31dcd17..0000000000 --- a/TargetLibraries/PULPOpen/src/dory_dma.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * dory_dma.c - * Alessio Burrello - * - * Copyright (C) 2019-2020 University of Bologna - * - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "dory_dma.h" - -#include "pmsis.h" - -#ifndef MCHAN_BASE_ADDR -// FIXME: For GAP9, this must point to ARCHI_MCHAN_EXT_ADDR!!! -// In PULP-SDK for Kraken, this is fixed. -// GAP8 hardware to be tested... -#define MCHAN_BASE_ADDR (ARCHI_MCHAN_DEMUX_ADDR) // CLUSTER_MCHAN_ADDR -#endif -#define MCHAN_EVENT -// #define MCHAN_POLLED -#ifdef MCHAN_EVENT -#define MCHAN_EVENT_BIT (ARCHI_CL_EVT_DMA0) // 8 -#endif -#include "mchan.h" - -#if defined(MCHAN_POLLED) -#define MCHAN_FLAGS (MCHAN_CMD_FLAG_INCREMENTAL) -#elif defined(MCHAN_EVENT) -#define MCHAN_FLAGS (MCHAN_CMD_FLAG_EVENT_ENABLE | MCHAN_CMD_FLAG_INCREMENTAL) -#elif defined(MCHAN_INTERRUPT) -#define MCHAN_FLAGS \ - (MCHAN_CMD_FLAG_INTERRUPT_ENABLE | MCHAN_CMD_FLAG_INCREMENTAL) -#endif - -#define MCHAN_FLAGS_1D (MCHAN_FLAGS) -#define MCHAN_FLAGS_2D (MCHAN_FLAGS | MCHAN_CMD_FLAG_2D_TRANSFER_EXTERNAL) - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -void dory_dma_memcpy_hwc_to_chw(DMA_copy *copy) { - int core_id = pi_core_id(); - int Log2Core = log2(NUM_CORES); - int number_of_copies_per_core = - (copy->length_1d_copy >> Log2Core) + - ((copy->length_1d_copy & (NUM_CORES - 1)) != 0); - int start_pixel, stop_pixel; // "pixel" is a misnomer; the CHANNELS are - // divided between the cores - // this function assumes that a DW tile is always as wide as the complete - // feature map (this is enforced by DORY's tiler) - start_pixel = MIN(number_of_copies_per_core * core_id, copy->length_1d_copy); - stop_pixel = - MIN(start_pixel + number_of_copies_per_core, copy->length_1d_copy); - void *ext = copy->ext + start_pixel; - void *loc = copy->loc + copy->number_of_1d_copies * - copy->number_of_2d_copies * start_pixel; - const int size_2d = copy->number_of_1d_copies * copy->number_of_2d_copies; - - for (int i = start_pixel; i < stop_pixel; i++) { - mchan_transfer_t trans = {.cmd = size_2d | - copy->dir << MCHAN_CMD_SHIFT_DIRECTION | - MCHAN_FLAGS_2D, - .size = size_2d, - .ext = ext, - .loc = loc, - .ext_size_1d = 1, // one byte at a time... - .ext_stride_1d = copy->stride_1d}; - mchan_transfer_push_2d(trans); -#ifdef ALWAYS_BLOCK_DMA_TRANSFERS // needed on GAP8 board - dory_dma_barrier(copy); -#endif - ext += 1; // next channel - loc += copy->number_of_1d_copies * copy->number_of_2d_copies; - } -} - -void dory_dma_memcpy_1d_async(DMA_copy *copy) { - if (pi_core_id() == 0) { - mchan_transfer_t trans = { - .cmd = copy->length_1d_copy * copy->number_of_1d_copies * - copy->number_of_2d_copies | - (copy->dir << MCHAN_CMD_SHIFT_DIRECTION) | MCHAN_FLAGS_1D, - .size = copy->length_1d_copy * copy->number_of_1d_copies * - copy->number_of_2d_copies, - .ext = copy->ext, - .loc = copy->loc}; - mchan_transfer_push_1d(trans); - } -} - -void dory_dma_memcpy_2d_async(DMA_copy *copy) { - if (pi_core_id() == 0) { - const int size_2d = copy->number_of_1d_copies * copy->length_1d_copy * - copy->number_of_2d_copies; - const int stride = - (copy->number_of_2d_copies == 1) ? copy->stride_1d : copy->stride_2d; - const int size_1d = (copy->number_of_2d_copies == 1) - ? copy->length_1d_copy - : copy->length_1d_copy * copy->number_of_1d_copies; - - mchan_transfer_t trans = {.cmd = size_2d | - copy->dir << MCHAN_CMD_SHIFT_DIRECTION | - MCHAN_FLAGS_2D, - .size = size_2d, - .ext = copy->ext, - .loc = copy->loc, - .ext_size_1d = size_1d, - .ext_stride_1d = stride}; - mchan_transfer_push_2d(trans); - } -} - -void dory_dma_memcpy_3d_async(DMA_copy *copy) { - int core_id = pi_core_id(); - if (core_id == 0) { - int Log2Core = log2(1); - int number_of_2d_copies_per_core = (copy->number_of_2d_copies >> Log2Core) + - ((copy->number_of_2d_copies & (0)) != 0); - int start_pixel, stop_pixel; - start_pixel = - MIN(number_of_2d_copies_per_core * core_id, copy->number_of_2d_copies); - stop_pixel = MIN(start_pixel + number_of_2d_copies_per_core, - copy->number_of_2d_copies); - void *ext = copy->ext + copy->stride_2d * start_pixel; - void *loc = copy->loc + - copy->length_1d_copy * copy->number_of_1d_copies * start_pixel; - const int size_2d = copy->number_of_1d_copies * copy->length_1d_copy; - - for (int i = start_pixel; i < stop_pixel; i++) { - mchan_transfer_t trans = {.cmd = size_2d | - copy->dir << MCHAN_CMD_SHIFT_DIRECTION | - MCHAN_FLAGS_2D, - .size = size_2d, - .ext = ext, - .loc = loc, - .ext_size_1d = copy->length_1d_copy, - .ext_stride_1d = copy->stride_1d}; - mchan_transfer_push_2d(trans); -#ifdef ALWAYS_BLOCK_DMA_TRANSFERS // needed on GAP8 board - // dory_dma_barrier(copy); -#endif - loc += size_2d; - ext += copy->stride_2d; - } - } -} - -void dory_dma_memcpy_async(DMA_copy *copy) { - if (copy->hwc_to_chw == 1) { - dory_dma_memcpy_hwc_to_chw(copy); - } else if ((copy->number_of_2d_copies == 1 && - copy->number_of_1d_copies == 1) || - (copy->stride_1d == copy->length_1d_copy && - copy->number_of_1d_copies * copy->length_1d_copy == - copy->stride_2d) || - (copy->number_of_2d_copies == 1 && - copy->length_1d_copy == copy->stride_1d)) { - dory_dma_memcpy_1d_async(copy); - } else if ((copy->number_of_2d_copies == 1) || - (copy->length_1d_copy == copy->stride_1d)) { // wrong! - dory_dma_memcpy_2d_async(copy); - } else { - dory_dma_memcpy_3d_async(copy); - } -} - -void dory_dma_memcpy_1d_mindims_async(DMA_copy *copy) { - mchan_transfer_t trans = { - .cmd = copy->mchan_cmd, .ext = copy->ext, .loc = copy->loc}; - mchan_transfer_push_1d(trans); -} - -void dory_dma_memcpy_2d_mindims_async(DMA_copy *copy) { - mchan_transfer_t trans = {.cmd = copy->mchan_cmd, - .ext = copy->ext, - .loc = copy->loc, - .ext_size_1d = copy->length_1d_copy, - .ext_stride_1d = copy->stride_1d}; - mchan_transfer_push_2d(trans); -} - -void dory_dma_memcpy_3d_mindims_async(DMA_copy *copy) { - void *ext = copy->ext; - void *loc = copy->loc; - const int length_2d_copy = - copy->mchan_cmd & ((1 << MCHAN_TRANSFER_LEN_SIZE) - 1); - - for (int i = 0; i < copy->number_of_2d_copies; i++) { - mchan_transfer_t trans = {.cmd = copy->mchan_cmd, - .ext = ext, - .loc = loc, - .ext_size_1d = copy->length_1d_copy, - .ext_stride_1d = copy->stride_1d}; - mchan_transfer_push_2d(trans); - loc += length_2d_copy; - ext += copy->stride_2d; -#ifdef ALWAYS_BLOCK_DMA_TRANSFERS // needed on GAP8 board - // dory_dma_barrier(copy); -#endif - } -} - -void dory_dma_memcpy_mindims_async(DMA_copy *copy) { - if (copy->number_of_2d_copies == 1 && copy->number_of_1d_copies == 1) { - dory_dma_memcpy_1d_mindims_async(copy); - } else if (copy->number_of_2d_copies == 1) { - dory_dma_memcpy_2d_mindims_async(copy); - } else { - dory_dma_memcpy_3d_mindims_async(copy); - } -} - -void dory_dma_free(DMA_copy *copy) { mchan_transfer_free(copy->tid); } - -void dory_dma_barrier(DMA_copy *copy) { mchan_transfer_wait(copy->tid); } - -int dory_dma_allocate() { return mchan_transfer_get_id(); } diff --git a/cmake/snitch/snitch.cmake b/cmake/snitch/snitch.cmake index 4170a99aab..9a12366fbd 100644 --- a/cmake/snitch/snitch.cmake +++ b/cmake/snitch/snitch.cmake @@ -1,3 +1,7 @@ +if(NOT DEFINED ENV{SNITCH_HOME}) + message(FATAL_ERROR "Environment variable SNITCH_HOME not set.") +endif() + set(SNITCH_HOME $ENV{SNITCH_HOME}) set(SNITCH_RUNTIME_HOME ${SNITCH_HOME}/sw/snRuntime) From a23b15f7704bd88f056fbdc6c7461c4a5441614d Mon Sep 17 00:00:00 2001 From: Philip Wiese Date: Fri, 12 Sep 2025 17:47:05 +0200 Subject: [PATCH 06/28] Split CI Workflows by Platform and Task, Improve Formatting and Linting Reliability (#108) - Added CI badges to the README - Added YAML linting to CI - Added missing license headers and C header include guards - Extended the pre-commit hooks to remove trailing whitespace, check licenses, format, and lint files - Split CI into multiple workflow files: one per platform, one for lint & license, one for general Deeploy tests, one for infrastructure, and two for Docker flows, improving maintainability and status reporting - Extended CI to check license in CMake and YAML files - Removed all trailing whitespace - Fix license CI check and prevent potential issues with `jq` installation --- .clang-format | 3 +- .devcontainer.json | 44 +- .github/workflows/CI.yml | 1091 ----------------- .github/workflows/GenerateCCache.yml | 45 - .github/workflows/GitLabCI.yml | 19 - ...tRunnerChimera.yml => _runner-chimera.yml} | 14 +- ...tRunnerCortexM.yml => _runner-cortexm.yml} | 11 +- ...tRunnerGeneric.yml => _runner-generic.yml} | 11 +- ...tRunnerMempool.yml => _runner-mempool.yml} | 11 +- ...ner-siracusa-neureka-tiled-sequential.yml} | 29 +- ...yml => _runner-siracusa-neureka-tiled.yml} | 25 +- ... => _runner-siracusa-tiled-sequential.yml} | 17 +- ...iracusa.yml => _runner-siracusa-tiled.yml} | 12 +- ...unnerSiracusa.yml => _runner-siracusa.yml} | 11 +- ...ml => _runner-snitch-tiled-sequential.yml} | 30 +- ...estRunnerSnitch.yml => _runner-snitch.yml} | 14 +- ...unnerSoftHier.yml => _runner-softhier.yml} | 11 +- .github/workflows/_select-env.yml | 48 + .github/workflows/ci-deeploy-testing.yml | 78 ++ .github/workflows/ci-deeploy.yml | 238 ++++ .github/workflows/ci-lint.yml | 108 ++ .github/workflows/ci-platform-chimera.yml | 41 + .github/workflows/ci-platform-cortexm.yml | 59 + .github/workflows/ci-platform-generic.yml | 97 ++ .github/workflows/ci-platform-mempool.yml | 74 ++ .../ci-platform-siracusa-neureka-tiled.yml | 146 +++ .../workflows/ci-platform-siracusa-tiled.yml | 201 +++ .github/workflows/ci-platform-siracusa.yml | 89 ++ .../workflows/ci-platform-snitch-tiled.yml | 50 + .github/workflows/ci-platform-snitch.yml | 51 + .github/workflows/ci-platform-softhier.yml | 39 + ...erDeeploy.yml => docker-build-deeploy.yml} | 23 +- ...olchain.yml => docker-build-toolchain.yml} | 19 +- .github/workflows/infra-generate-ccache.yml | 50 + ...n.yml => infra-generate-documentation.yml} | 13 +- .gitlab/issue_templates/issue_template.md | 24 - .gitlab/merge_request_templates/MRTemplate.md | 19 - .pre-commit-config.yaml | 83 +- .vscode/c_cpp_properties.json | 20 +- .vscode/launch.json | 170 +-- .yamllint | 33 + CHANGELOG.md | 11 +- CMakeLists.txt | 6 +- Deeploy/AbstractDataTypes.py | 4 +- .../CodeTransformationPasses/PrintInputs.py | 4 +- .../Generic/Templates/FloatGemmTemplate.py | 6 +- .../Templates/FloatLayernormTemplate.py | 2 +- .../Generic/Templates/FloatMaxPoolTemplate.py | 2 +- .../Generic/Templates/FloatPadTemplate.py | 2 +- .../Templates/FloatReduceSumTemplate.py | 2 +- .../Generic/Templates/QuantTemplate.py | 10 +- .../Generic/Templates/SliceTemplate.py | 2 +- Deeploy/Targets/PULPOpen/DMA/L3Dma.py | 26 + Deeploy/Targets/PULPOpen/DMA/MchanDma.py | 26 + .../PULPOpen/Templates/FloatConvTemplate.py | 40 +- .../PULPOpen/Templates/FloatGemmTemplate.py | 2 +- .../Templates/FloatLayernormTemplate.py | 12 +- .../PULPOpen/Templates/FloatMatMulTemplate.py | 6 +- .../Templates/FloatMaxPoolTemplate.py | 4 +- .../Targets/PULPOpen/Templates/SGDTemplate.py | 4 +- .../SoftmaxCrossEntropyLossTemplate.py | 6 +- .../PULPOpen/Templates/TallGEMMTemplate.py | 8 +- .../Templates/UniformRequantShiftTemplate.py | 2 +- .../LayernormTileConstraint.py | 26 + Deeploy/Targets/Snitch/DMA/SnitchDma.py | 26 + .../Targets/Snitch/Templates/AddTemplate.py | 2 +- .../Snitch/Templates/FloatGemmTemplate.py | 29 +- .../Snitch/Templates/FloatSoftmaxTemplate.py | 2 +- .../Targets/Snitch/Templates/GemmTemplate.py | 25 + .../Snitch/Templates/RqGemmTemplate.py | 25 + Deeploy/Targets/Snitch/Templates/__init__.py | 25 + .../TileConstraints/GemmTileConstraint.py | 26 + .../TileConstraints/RqGemmTileConstraint.py | 26 + Deeploy/Targets/Snitch/__init__.py | 25 + Deeploy/TilingExtension/AsyncDma.py | 26 + .../TilingHoistingMixIn.py | 26 + .../TilingPrototypes.py | 2 +- DeeployTest/CMakeLists.txt | 4 + DeeployTest/Platforms/Chimera/CMakeLists.txt | 4 + DeeployTest/Platforms/Generic/CMakeLists.txt | 4 + DeeployTest/Platforms/MemPool/CMakeLists.txt | 4 + DeeployTest/Platforms/PULPOpen/CMakeLists.txt | 4 + DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt | 4 + DeeployTest/Platforms/Siracusa/CMakeLists.txt | 4 + DeeployTest/Platforms/Snitch/CMakeLists.txt | 4 + DeeployTest/Platforms/SoftHier/CMakeLists.txt | 4 + DeeployTest/testDmas.py | 26 + DeeployTest/testRunner_siracusa_l3dma.py | 26 + DeeployTest/testRunner_siracusa_mchandma.py | 26 + DeeployTest/testRunner_snitch.py | 2 +- DeeployTest/testRunner_snitch_dma.py | 26 + DeeployTest/testUtils/dmaUtils.py | 26 + DeeployTest/testUtils/tilingUtils.py | 26 + Makefile | 61 +- README.md | 21 +- TargetLibraries/CMSIS/CMakeLists.txt | 4 + TargetLibraries/Chimera/CMakeLists.txt | 4 + TargetLibraries/Generic/CMakeLists.txt | 8 +- .../Generic/inc/kernel/Hardswish.h | 7 +- .../Generic/inc/kernel/RQHardswish.h | 5 + TargetLibraries/Generic/inc/kernel/Relu.h | 7 +- TargetLibraries/MemPool/CMakeLists.txt | 4 + .../MemPool/cmake/mempool-runtime.cmake | 4 + TargetLibraries/PULPOpen/CMakeLists.txt | 4 + .../PULPOpen/cmake/pulp-sdk-base.cmake | 4 + .../PULPOpen/cmake/pulp-sdk-pulp-open.cmake | 4 + .../PULPOpen/cmake/pulp-sdk-siracusa.cmake | 4 + TargetLibraries/PULPOpen/inc/kernel/Conv.h | 7 +- TargetLibraries/PULPOpen/inc/kernel/GELU.h | 7 +- .../PULPOpen/inc/kernel/Layernorm.h | 7 +- TargetLibraries/PULPOpen/inc/kernel/Matmul.h | 7 +- TargetLibraries/PULPOpen/inc/kernel/MaxPool.h | 7 +- .../PULPOpen/inc/kernel/RQiHardswish.h | 5 + TargetLibraries/PULPOpen/inc/kernel/Relu.h | 7 +- .../PULPOpen/inc/kernel/RequantShift.h | 5 + TargetLibraries/PULPOpen/inc/kernel/Softmax.h | 7 +- .../PULPOpen/inc/kernel/UniformRequantShift.h | 7 +- TargetLibraries/PULPOpen/inc/kernel/gemm.h | 7 +- TargetLibraries/PULPOpen/inc/kernel/gemv.h | 5 + .../PULPOpen/inc/kernel/iRMSnorm.h | 5 + TargetLibraries/PULPOpen/inc/mchan_siracusa.h | 26 + TargetLibraries/PULPOpen/inc/pulp_core.h | 32 +- TargetLibraries/Snitch/CMakeLists.txt | 4 + .../cmake/snitch-runtime-precompiled.cmake | 4 + TargetLibraries/Snitch/inc/dmaStruct.h | 7 +- TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h | 32 +- TargetLibraries/Snitch/inc/kernel/Softmax.h | 33 +- .../Snitch/inc/kernel/UniformRequantShift.h | 7 +- TargetLibraries/Snitch/inc/kernel/iNoNorm.h | 5 + TargetLibraries/Snitch/inc/kernel/iSoftmax.h | 5 + TargetLibraries/Snitch/src/Gemm_fp32.c | 26 + TargetLibraries/Snitch/src/Gemm_s8.c | 26 + TargetLibraries/Snitch/src/Softmax_fp32.c | 26 + .../Snitch/src/snitch_nn_add_i8_i8_i8.c | 2 + TargetLibraries/SoftHier/CMakeLists.txt | 10 +- .../SoftHier/cmake/softhier-runtime.cmake | 8 +- cmake/Util.cmake | 4 + cmake/chimera/chimera-sdk.cmake | 4 + cmake/chimera/toolchain_llvm.cmake | 6 +- cmake/cmsis/cmsis.cmake | 4 + cmake/cmsis/qemu.cmake | 4 + cmake/cmsis/toolchain_gcc.cmake | 4 + cmake/cmsis/toolchain_llvm.cmake | 4 + cmake/common.cmake | 4 + cmake/generic/generic.cmake | 4 + cmake/generic/toolchain_llvm.cmake | 4 + cmake/mempool/mempool.cmake | 4 + cmake/mempool/mempool_ita.cmake | 4 + cmake/mempool/minpool.cmake | 4 + cmake/mempool/toolchain_gcc.cmake | 4 + cmake/mempool/toolchain_llvm.cmake | 4 + cmake/pulp/pulp-open/pulp-open.cmake | 4 + cmake/pulp/pulp.cmake | 4 + cmake/pulp/siracusa/siracusa.cmake | 4 + cmake/pulp/toolchain_gcc.cmake | 4 + cmake/pulp/toolchain_llvm.cmake | 4 + cmake/simulation.cmake | 4 + cmake/snitch/snitch.cmake | 4 + .../snitch_cluster/snitch_cluster.cmake | 4 + cmake/snitch/toolchain_llvm.cmake | 4 + cmake/softhier/softhier_gvsoc.cmake | 4 + cmake/softhier/toolchain_gcc.cmake | 18 +- requirements-dev.txt | 1 + scripts/gen_changelog.py | 26 + 164 files changed, 2930 insertions(+), 1537 deletions(-) delete mode 100644 .github/workflows/CI.yml delete mode 100644 .github/workflows/GenerateCCache.yml delete mode 100644 .github/workflows/GitLabCI.yml rename .github/workflows/{TestRunnerChimera.yml => _runner-chimera.yml} (84%) rename .github/workflows/{TestRunnerCortexM.yml => _runner-cortexm.yml} (83%) rename .github/workflows/{TestRunnerGeneric.yml => _runner-generic.yml} (83%) rename .github/workflows/{TestRunnerMempool.yml => _runner-mempool.yml} (83%) rename .github/workflows/{TestRunnerTiledSiracusaWithNeurekaSequential.yml => _runner-siracusa-neureka-tiled-sequential.yml} (79%) rename .github/workflows/{TestRunnerTiledSiracusaWithNeureka.yml => _runner-siracusa-neureka-tiled.yml} (83%) rename .github/workflows/{TestRunnerTiledSiracusaSequential.yml => _runner-siracusa-tiled-sequential.yml} (85%) rename .github/workflows/{TestRunnerTiledSiracusa.yml => _runner-siracusa-tiled.yml} (89%) rename .github/workflows/{TestRunnerSiracusa.yml => _runner-siracusa.yml} (84%) rename .github/workflows/{TestRunnerTiledSnitchSequential.yml => _runner-snitch-tiled-sequential.yml} (79%) rename .github/workflows/{TestRunnerSnitch.yml => _runner-snitch.yml} (84%) rename .github/workflows/{TestRunnerSoftHier.yml => _runner-softhier.yml} (81%) create mode 100644 .github/workflows/_select-env.yml create mode 100644 .github/workflows/ci-deeploy-testing.yml create mode 100644 .github/workflows/ci-deeploy.yml create mode 100644 .github/workflows/ci-lint.yml create mode 100644 .github/workflows/ci-platform-chimera.yml create mode 100644 .github/workflows/ci-platform-cortexm.yml create mode 100644 .github/workflows/ci-platform-generic.yml create mode 100644 .github/workflows/ci-platform-mempool.yml create mode 100644 .github/workflows/ci-platform-siracusa-neureka-tiled.yml create mode 100644 .github/workflows/ci-platform-siracusa-tiled.yml create mode 100644 .github/workflows/ci-platform-siracusa.yml create mode 100644 .github/workflows/ci-platform-snitch-tiled.yml create mode 100644 .github/workflows/ci-platform-snitch.yml create mode 100644 .github/workflows/ci-platform-softhier.yml rename .github/workflows/{BuildDockerDeeploy.yml => docker-build-deeploy.yml} (88%) rename .github/workflows/{BuildDockerToolchain.yml => docker-build-toolchain.yml} (90%) create mode 100644 .github/workflows/infra-generate-ccache.yml rename .github/workflows/{documentation.yml => infra-generate-documentation.yml} (78%) delete mode 100644 .gitlab/issue_templates/issue_template.md delete mode 100644 .gitlab/merge_request_templates/MRTemplate.md create mode 100644 .yamllint diff --git a/.clang-format b/.clang-format index 6caaa71987..f71507a24b 100644 --- a/.clang-format +++ b/.clang-format @@ -2,6 +2,7 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 +--- # Use LLVM's style BasedOnStyle: LLVM -ColumnLimit: 80 +ColumnLimit: 80 diff --git a/.devcontainer.json b/.devcontainer.json index 3cbc1ab13f..40c726bb83 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -1,24 +1,24 @@ { - "image": "ghcr.io/pulp-platform/deeploy:main", - "name": "deeploy_main", - "customizations": { - "vscode": { - "extensions": [ - "ms-vscode.cpptools-extension-pack", - "twxs.cmake", - "josetr.cmake-language-support-vscode", - "ms-vscode.cmake-tools", - "ms-python.python", - "ms-vscode-remote.remote-containers", - "rioj7.command-variable" - ] - } - }, - "mounts": [ - { - "source": "${localWorkspaceFolder}", - "target": "/app/Deeploy", - "type": "bind" - } - ] + "image": "ghcr.io/pulp-platform/deeploy:main", + "name": "deeploy_main", + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cpptools-extension-pack", + "twxs.cmake", + "josetr.cmake-language-support-vscode", + "ms-vscode.cmake-tools", + "ms-python.python", + "ms-vscode-remote.remote-containers", + "rioj7.command-variable" + ] + } + }, + "mounts": [ + { + "source": "${localWorkspaceFolder}", + "target": "/app/Deeploy", + "type": "bind" + } + ] } \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml deleted file mode 100644 index 5415a4a251..0000000000 --- a/.github/workflows/CI.yml +++ /dev/null @@ -1,1091 +0,0 @@ -name: CI - -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-docker-image-and-runner: - runs-on: ubuntu-latest - outputs: - image: ${{ steps.set-docker-image.outputs.image }} - runner: ${{ steps.set-runner.outputs.runner }} - steps: - - id: set-docker-image - run: | - if [[ -n "${{ github.event.inputs.docker_image_deeploy }}" ]]; then - IMAGE="${{ github.event.inputs.docker_image_deeploy }}" - elif [[ "${{ github.ref }}" == refs/tags/* ]]; then - TAG_NAME="${GITHUB_REF##refs/tags/}" - IMAGE="ghcr.io/pulp-platform/deeploy:${TAG_NAME}" - elif [[ "${{ github.ref_name }}" == "main" ]]; then - IMAGE="ghcr.io/pulp-platform/deeploy:main" - else - IMAGE="ghcr.io/pulp-platform/deeploy:devel" - fi - echo "Selected image: ${IMAGE}" - echo "image=${IMAGE}" >> $GITHUB_OUTPUT - - - id: set-runner - run: | - if [[ "${{ github.repository }}" == "pulp-platform/Deeploy" ]]; then - echo "Selected self-hosted runner for Deeploy repository" - echo "runner=self-hosted" >> $GITHUB_OUTPUT - else - echo "Selected ubuntu-latest runner for external repository" - echo "runner=ubuntu-latest" >> $GITHUB_OUTPUT - fi - - build-deeploy: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - - ### Generic Tests ### - generic-kernels: - uses: ./.github/workflows/TestRunnerGeneric.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - MultIO - test1DConvolution - test2DConvolution - test1DDWConvolution - test2DDWConvolution - test1DPad - test2DPad - testGEMM - testMatMul - testMatMulAdd - testMaxPool - testRQConv - testRQMatMul - testReduceSum - testReduceMean - testSlice - testRequantizedDWConv - test2DRequantizedConv - iSoftmax - testFloatAdder - testFloatGEMM - testFloat2DConvolution - testFloat2DConvolutionBias - testFloat2DConvolutionZeroBias - testFloatLayerNorm - testFloatDiv - testFloat2DDWConvolution - testFloat2DDWConvolutionBias - testFloat2DDWConvolutionZeroBias - testFloatRelu - testFloatMaxPool - testFloatMatmul - testFloatReshapeWithSkipConnection - testFloatSoftmax - testFloatTranspose - testFloatMul - Quant - Dequant - QuantizedLinear - - - generic-models: - uses: ./.github/workflows/TestRunnerGeneric.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - simpleRegression - WaveFormer - simpleCNN - ICCT - ICCT_ITA - ICCT_8 - ICCT_ITA_8 - miniMobileNet - miniMobileNetv2 - CCT/CCT_1_16_16_8 - testFloatDemoTinyViT - - ### SoftHier Tests ### - softhier-kernels: - uses: ./.github/workflows/TestRunnerSoftHier.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - - ### CortexM Tests ### - cortexm-kernels: - uses: ./.github/workflows/TestRunnerCortexM.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - MultIO - test1DPad - test2DPad - testMatMul - testMatMulAdd - testMaxPool - testRQConv - testReduceSum - testReduceMean - testSlice - - cortexm-models: - uses: ./.github/workflows/TestRunnerCortexM.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - simpleRegression - WaveFormer - - - ### Chimera Tests ### - chimera-kernels: - uses: ./.github/workflows/TestRunnerChimera.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - simulators: | - gvsoc - - - ### Snitch Tests ### - snitch-kernels: - uses: ./.github/workflows/TestRunnerSnitch.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - iSoftmax - TestiNoNorm - TestAdderLarge - TestiSoftmaxLarge - testMatMul - testRQGEMM - TestRQAdd - testRQGEMMTransB - testFloatSoftmax - num-cores: 9 - simulators: | - gvsoc - - snitch-kernels-tiled-singlebuffer-L2: - uses: ./.github/workflows/TestRunnerTiledSnitchSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "TestiNoNorm", - "L1": [5000, 10000] - }, - { - "name": "TestAdderLarge", - "L1": [5000, 10000] - }, - { - "name": "TestiSoftmaxLarge", - "L1": [5000, 10000] - }, - { - "name": "testRQGEMM", - "L1": [2000, 5000] - }, - { - "name": "testFloatSoftmax", - "L1": [2000, 5000, 10000] - }, - - { - "name": "TestRQAdd", - "L1": [5000, 10000] - }, - - { - "name": "testFloatGEMM", - "L1": [2000, 5000, 10000] - }, - - { - "name": "testFloatGEMMtransB", - "L1": [2000, 5000, 10000] - } - ] - simulators: | - gvsoc - - ### Mempool Tests ### - mempool-kernels: - uses: ./.github/workflows/TestRunnerMempool.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - MultIO - test1DConvolution - test2DConvolution - test1DDWConvolution - test2DDWConvolution - test1DPad - test2DPad - testGEMM - testMatMul - testMatMulAdd - testMaxPool - testRQConv - testRQGEMM - testRQMatMul - testReduceSum - testReduceMean - testSlice - testRequantizedDWConv - test2DRequantizedConv - - mempool-models: - uses: ./.github/workflows/TestRunnerMempool.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - simpleRegression - simpleCNN - ICCT - ICCT_ITA - ICCT_8 - ICCT_ITA_8 - miniMobileNet - miniMobileNetv2 - - - ### Siracusa Tests ### - siracusa-kernels: - uses: ./.github/workflows/TestRunnerSiracusa.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - Adder - MultIO - test1DPad - test2DPad - testMatMul - testMatMulAdd - testRequantizedDWConv - test2DRequantizedConv - iSoftmax - testConcat - testRMSNorm - trueIntegerDivSandwich - Hardswish - RQHardswish - testBacktracking - testFloatAdder - testFloatGEMM - testFloat2DConvolution - testFloatLayerNorm - testFloatRelu - testFloatMaxPool - testFloatMatmul - testFloatSoftmax - testFloatTranspose - testFloatMul - Quant - Dequant - testFloatReduceSum - testFloatSoftmaxGrad - testFloatSoftmaxCrossEntropy - testFloatSoftmaxCrossEntropyGrad - QuantizedLinear - num-cores: 8 - - siracusa-models: - uses: ./.github/workflows/TestRunnerSiracusa.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-names: | - simpleRegression - miniMobileNet - miniMobileNetv2 - Attention - MLPerf/KeywordSpotting - MLPerf/ImageClassification - MLPerf/AnomalyDetection - CCT/CCT_1_16_16_8 - testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8 - num-cores: 8 - - siracusa-kernels-tiled-singlebuffer-L2: - uses: ./.github/workflows/TestRunnerTiledSiracusaSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "testMatMul", - "L1": [64000, 32000, 16000] - }, - { - "name": "test2DRequantizedConv", - "L1": [8000, 6000, 4000] - }, - { - "name": "test2DRequantizedStriddedPaddedConv", - "L1": [600] - }, - { - "name": "testRequantizedDWConv", - "L1": [2561] - }, - { - "name": "iSoftmax", - "L1": [800, 500, 300] - }, - { - "name": "testConcat", - "L1": [32000, 16000, 8000] - }, - { - "name": "testRMSNorm", - "L1": [2048, 1024, 512] - }, - { - "name": "Hardswish", - "L1": [750] - }, - { - "name": "RQHardswish", - "L1": [750] - }, - { - "name": "testFloatGEMM", - "L1": [8000] - }, - { - "name": "testFloat2DConvolution", - "L1": [8000] - }, - { - "name": "testFloatLayerNorm", - "L1": [2000] - }, - { - "name": "testFloatRelu", - "L1": [2000] - }, - { - "name": "testFloatMaxPool", - "L1": [2000] - }, - { - "name": "testFloatMatmul", - "L1": [2000] - }, - { - "name": "testFloatSoftmax", - "L1": [4000] - }, - { - "name": "testFloatTranspose", - "L1": [2000] - }, - { - "name": "testFloatMul", - "L1": [2000] - }, - { - "name": "largeFloatAdd", - "L1": [220000] - } - ] - num-cores: 8 - - siracusa-kernels-tiled-doublebuffer-L2: - uses: ./.github/workflows/TestRunnerTiledSiracusaSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "testMatMul", - "L1": [64000, 32000, 16000] - }, - { - "name": "test2DRequantizedConv", - "L1": [8000, 6000, 5000] - }, - { - "name": "testRequantizedDWConv", - "L1": [5121] - }, - { - "name": "iSoftmax", - "L1": [1600, 1000, 600] - }, - { - "name": "testConcat", - "L1": [64000, 32000, 16000] - }, - { - "name": "testRMSNorm", - "L1": [4096, 2048, 1024] - }, - { - "name": "Hardswish", - "L1": [750] - }, - { - "name": "RQHardswish", - "L1": [800] - }, - { - "name": "testFloatGEMM", - "L1": [8000] - }, - { - "name": "testFloat2DConvolution", - "L1": [15000] - }, - { - "name": "testFloatLayerNorm", - "L1": [2000] - }, - { - "name": "testFloatRelu", - "L1": [2000] - }, - { - "name": "testFloatMaxPool", - "L1": [5000] - }, - { - "name": "testFloatMatmul", - "L1": [5000] - }, - { - "name": "testFloatSoftmax", - "L1": [8000] - }, - { - "name": "testFloatTranspose", - "L1": [2000] - }, - { - "name": "testFloatMul", - "L1": [2000] - } - ] - num-cores: 8 - double-buffer: true - - siracusa-models-tiled-singlebuffer-L2: - strategy: - fail-fast: false - matrix: - test-data: - - name: "simpleRegression" - L1: [45000, 30000, 15000] - - name: "miniMobileNet" - L1: [60000, 12000, 6000, 3000] - - name: "miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - name: "Attention" - L1: [60000, 10000, 5000] - - name: "microLlama/microLlama1" - L1: [60000, 10000, 5000] - - name: "microLlama/microLlama8" - L1: [60000, 10000, 5000] - - name: "microLlama/microLlama8_parallel" - L1: [60000, 10000, 5000] - - name: "MLPerf/KeywordSpotting" - L1: [64000] - - name: "MLPerf/ImageClassification" - L1: [64000] - - name: "MLPerf/AnomalyDetection" - L1: [64000] - - name: "CCT/CCT_1_16_16_8" - L1: [64000] - - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8" - L1: [64000] - num-cores: - - 8 - uses: ./.github/workflows/TestRunnerTiledSiracusa.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - test-name: ${{ matrix.test-data.name }} - num-cores: ${{ matrix.num-cores }} - L1: ${{ toJson(matrix.test-data.L1) }} - - siracusa-models-tiled-singlebuffer-L3: - strategy: - fail-fast: false - matrix: - test-data: - - name: "simpleRegression" - L1: [45000, 30000, 16000] # SCHEREMO: 15000 leads to non-2d transfers in L3! - - name: "miniMobileNet" - L1: [60000, 12000, 6000] # SCHEREMO: 3000 leads to non-2d transfers in L3! - - name: "miniMobileNetv2" - L1: [60000, 16000, 12000, 8000] - - name: "Attention" - L1: [60000, 10000, 5000, 2500] - - name: "Transformer" - L1: [60000, 30000, 15000] - - name: "microLlama/microLlama1" - L1: [60000, 10000, 5000] - - name: "CCT/CCT_2_32_32_128" - L1: [128000] - - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_128" - L1: [64000] - num-cores: - - 8 - default-memory-level: - - "L3" - uses: ./.github/workflows/TestRunnerTiledSiracusa.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.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 }} - - # TEMPORARILY DISABLE L3 TRANSFER DUE TO DRIVER BUG CAUSING SPORADIC CRASH - siracusa-models-tiled-doublebuffer-L3: - strategy: - fail-fast: false - matrix: - test-data: - - name: "simpleRegression" - L1: [60000, 45000, 30000] - - name: "miniMobileNet" - L1: [60000, 24000, 12000, 6000] - - name: "miniMobileNetv2" - L1: [60000, 32000, 24000, 16000] - - name: "Attention" - L1: [60000, 20000, 10000, 5000] - - name: "Transformer" - L1: [60000, 30000, 15000] - - name: "microLlama/microLlama1" - L1: [60000, 20000, 10000] - - name: "microLlama/microLlama8" - L1: [60000, 20000, 10000] - - name: "microLlama/microLlama8_parallel" - L1: [60000, 20000, 10000] - - name: "CCT/CCT_2_32_32_128" - L1: [128000] - - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_128" - L1: [64000] - num-cores: - - 8 - double-buffer: - - true - default-memory-level: - - "L3" - uses: ./.github/workflows/TestRunnerTiledSiracusa.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.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 }} - - siracusa-neureka-kernels-tiled-singlebuffer-L2: - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "testRequantizedLinear", - "L1": [16000] - }, - { - "name": "testPointwise", - "L1": [32000] - }, - { - "name": "testPointwiseConvBNReLU", - "L1": [32000] - }, - { - "name": "testPointwiseUnsignedWeights", - "L1": [32000] - } - ] - num-cores: 8 - - siracusa-neureka-kernels-tiled-doublebuffer-L2: - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "testRequantizedLinear", - "L1": [16000] - }, - { - "name": "testPointwise", - "L1": [32000] - }, - { - "name": "testPointwiseConvBNReLU", - "L1": [32000] - }, - { - "name": "testPointwiseUnsignedWeights", - "L1": [32000] - } - ] - num-cores: 8 - double-buffer: true - - siracusa-neureka-models-tiled-singlebuffer-L3: - strategy: - fail-fast: false - matrix: - test-data: - - name: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - name: "Attention" - L1: [2500] - - name: "Transformer" - L1: [15000] - - name: "microLlama/microLlama1" - L1: [10000] - num-cores: - - 8 - default-memory-level: - - "L3" - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeureka.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.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 }} - - siracusa-neureka-models-tiled-doublebuffer-L3: - strategy: - fail-fast: false - matrix: - test-data: - - name: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - name: "Attention" - L1: [5000] - - name: "Transformer" - L1: [30000] - num-cores: - - 8 - double-buffer: - - true - default-memory-level: - - "L3" - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeureka.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.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 }} - - siracusa-neureka-kernels-tiled-singlebuffer-L2-wmem: - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.outputs.image }} - tests-config: | - [ - { - "name": "testRequantizedLinear", - "L1": [16000] - }, - { - "name": "testPointwise", - "L1": [32000] - }, - { - "name": "testPointwiseConvBNReLU", - "L1": [32000] - }, - { - "name": "testPointwiseUnsignedWeights", - "L1": [32000] - } - ] - num-cores: 8 - neureka-wmem: true - - siracusa-neureka-models-tiled-doublebuffer-L3-wmem: - strategy: - fail-fast: false - matrix: - test-data: - - name: "miniMobileNet" - L1: [2000] # LMACAN: 1000 leads to non-2d transfers in L3! - - name: "Attention" - L1: [3500] - # - name: "Transformer" - # L1: [30000] - - name: "microLlama/microLlama1" - L1: [10000] - num-cores: - - 8 - double-buffer: - - true - default-memory-level: - - "L3" - neureka-wmem: - - true - uses: ./.github/workflows/TestRunnerTiledSiracusaWithNeureka.yml - needs: select-docker-image-and-runner - with: - runner: ${{ needs.select-docker-image-and-runner.outputs.runner }} - docker-image: ${{ needs.select-docker-image-and-runner.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 }} - - - ### Deeploy Extension and Internal Tests ### - deeploy-memory-allocation: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=75000 --memAllocStrategy=MiniMalloc - python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=60000 --memAllocStrategy=MiniMalloc --shouldFail - python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=90000 --memAllocStrategy=TetrisRandom - python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=75000 --memAllocStrategy=TetrisRandom --shouldFail - - deeploy-state-serialization: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p QEMU-ARM - python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p Siracusa - python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p MemPool - python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p Generic - shell: bash - - deeploy-memory-level-extension: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p QEMU-ARM - python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p Siracusa - python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p MemPool - python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p Generic - shell: bash - - deeploy-tiler-extension: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testTilerExtension.py -p Siracusa -t ./Tests/simpleRegression - python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN - python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul - python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool - python testTilerExtension.py -p Siracusa -t ./Tests/simpleRegression --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul --l1 2000 --shouldFail - python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool --l1 2000 --shouldFail - shell: bash - - deeploy-memory-allocation-extension: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testTilerExtension.py -p Siracusa -t ./Tests/simpleRegression - python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN - python testTilerExtension.py -p Siracusa -t ./Tests/miniMobileNet - python testTilerExtension.py -p Siracusa -t ./Tests/miniMobileNetv2 - python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul - python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool - shell: bash - - deeploy-typing: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testTypes.py - shell: bash - - deeploy-debug: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testPrintInputOutputTransformation.py -p Generic -t ./Tests/simpleRegression - python testPrintInputOutputTransformation.py -p Siracusa -t ./Tests/simpleRegression - python testDebugPrintPass.py -p Generic -t ./Tests/simpleRegression - shell: bash - - deeploy-regex-matching: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testRegexMatching.py - shell: bash - - deeploy-test-dmas: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: pip install -e . - - name: Run Test - run: | - cd DeeployTest - python testDmas.py - shell: bash - - linting: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - run: | - pip install -e . - cd DeeployTest - - name: Format Python - run: | - yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . - shell: bash - - name: Format Python Imports - run: | - isort --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c -v - autoflake -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "*/third_party/**" ./ - shell: bash - - name: Format C - run: | - python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format ./ scripts - shell: bash - - name: Format Python Licenses - run: | - grep -Lr "SPDX-License-Identifier: Apache-2.0" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude "run_clang_format.py" | grep ".*\.py$" || [[ $? == 1 ]] - shell: bash - - name: Format C Licenses - run: | - grep -Lr "SPDX-License-Identifier: Apache-2.0" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="runtime" | grep ".*\.c$" || [[ $? == 1 ]] - shell: bash - - name: Format C Header Licenses - run: | - grep -Lr "SPDX-License-Identifier: Apache-2.0" --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" . --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="runtime" | grep ".*\.h$" || [[ $? == 1 ]] - shell: bash - - generate-network-type-inference: - runs-on: ${{ needs.select-docker-image-and-runner.outputs.runner }} - needs: select-docker-image-and-runner - container: - image: ${{ needs.select-docker-image-and-runner.outputs.image }} - strategy: - fail-fast: false - matrix: - include: - - name: fail-input0 - platform: Generic - test: testTypeInferenceDifferentTypes - 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: testTypeInferenceDifferentTypes - 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: testTypeInferenceDifferentTypes - 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 - run: pip install -e . - - name: Run Test - 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/GenerateCCache.yml b/.github/workflows/GenerateCCache.yml deleted file mode 100644 index b22d04bd1e..0000000000 --- a/.github/workflows/GenerateCCache.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: GenerateCCache - -on: - workflow_dispatch: - inputs: - docker_image_deeploy: - description: 'Deeploy Image to use' - required: false - default: 'ghcr.io/pulp-platform/deeploy:devel' - schedule: - # Runs the workflow on the default branch every day at 1AM CET to keep the cache fresh - - cron: "0 1 * * *" - -jobs: - - generate-ccache: - runs-on: ubuntu-latest - container: - image: ${{ github.event.inputs.docker_image_deeploy || 'ghcr.io/pulp-platform/deeploy:devel' }} - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build Deeploy - 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/Adder - python testRunner_mempool.py -t ./Tests/Adder - python testRunner_cortexm.py -t ./Tests/Adder - python testRunner_snitch.py -t ./Tests/Adder - python testRunner_siracusa.py -t ./Tests/Adder - python testRunner_tiled_siracusa.py -t ./Tests/Adder - python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/Adder - - name: Clean and Upload CCache - uses: actions/cache@v4 - with: - path: /app/.ccache - key: ccache-ci - - \ No newline at end of file diff --git a/.github/workflows/GitLabCI.yml b/.github/workflows/GitLabCI.yml deleted file mode 100644 index c7e5b5d93c..0000000000 --- a/.github/workflows/GitLabCI.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: GitLabCI - -on: - # push: - # pull_request: - workflow_dispatch: - -jobs: - gitlab-ci: - runs-on: ubuntu-22.04 - steps: - - name: Check Gitlab CI - uses: pulp-platform/pulp-actions/gitlab-ci@v2 - # Skip on forks or pull requests from forks due to missing secrets. - if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) - with: - domain: iis-git.ee.ethz.ch - repo: github-mirror/Deeploy - token: ${{ secrets.GITLAB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/TestRunnerChimera.yml b/.github/workflows/_runner-chimera.yml similarity index 84% rename from .github/workflows/TestRunnerChimera.yml rename to .github/workflows/_runner-chimera.yml index daffbff246..d9fe7c58f2 100644 --- a/.github/workflows/TestRunnerChimera.yml +++ b/.github/workflows/_runner-chimera.yml @@ -1,6 +1,11 @@ -name: TestRunnerChimera +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-chimera + +"on": workflow_call: inputs: runner: @@ -14,7 +19,7 @@ on: type: string simulators: required: true - type: string + type: string jobs: test-runner-chimera: @@ -27,6 +32,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -51,4 +57,4 @@ jobs: done fi done - shell: bash \ No newline at end of file + shell: bash diff --git a/.github/workflows/TestRunnerCortexM.yml b/.github/workflows/_runner-cortexm.yml similarity index 83% rename from .github/workflows/TestRunnerCortexM.yml rename to .github/workflows/_runner-cortexm.yml index 2b30b8a0b5..995a3abbeb 100644 --- a/.github/workflows/TestRunnerCortexM.yml +++ b/.github/workflows/_runner-cortexm.yml @@ -1,6 +1,11 @@ -name: TestRunnerCortexM +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-cortexm + +"on": workflow_call: inputs: runner: @@ -24,6 +29,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -43,4 +49,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerGeneric.yml b/.github/workflows/_runner-generic.yml similarity index 83% rename from .github/workflows/TestRunnerGeneric.yml rename to .github/workflows/_runner-generic.yml index 92ec086cbf..7601330743 100644 --- a/.github/workflows/TestRunnerGeneric.yml +++ b/.github/workflows/_runner-generic.yml @@ -1,6 +1,11 @@ -name: TestRunnerGeneric +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-generic + +"on": workflow_call: inputs: runner: @@ -24,6 +29,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -43,4 +49,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerMempool.yml b/.github/workflows/_runner-mempool.yml similarity index 83% rename from .github/workflows/TestRunnerMempool.yml rename to .github/workflows/_runner-mempool.yml index 233964eaf1..bddf35b024 100644 --- a/.github/workflows/TestRunnerMempool.yml +++ b/.github/workflows/_runner-mempool.yml @@ -1,6 +1,11 @@ -name: TestRunnerMempool +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-mempool + +"on": workflow_call: inputs: runner: @@ -24,6 +29,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -43,4 +49,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml b/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml similarity index 79% rename from .github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml rename to .github/workflows/_runner-siracusa-neureka-tiled-sequential.yml index 783d0c5785..505fa72f02 100644 --- a/.github/workflows/TestRunnerTiledSiracusaWithNeurekaSequential.yml +++ b/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml @@ -1,6 +1,11 @@ -name: TestRunnerTiledSiracusaWithNeurekaSequential +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-siracusa-neureka-tiled-sequential + +"on": workflow_call: inputs: runner: @@ -25,20 +30,19 @@ on: default: false type: boolean memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string + required: false + default: "MiniMalloc" + type: string search-strategy: - required: false - default: "random-max" - type: string + 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: @@ -49,9 +53,13 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Install jq - run: apt-get install -y jq + run: | + export DEBIAN_FRONTEND=noninteractive + apt-get update -y + apt-get install -y jq - name: Cache ccache uses: actions/cache/restore@v4 with: @@ -74,4 +82,3 @@ jobs: done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerTiledSiracusaWithNeureka.yml b/.github/workflows/_runner-siracusa-neureka-tiled.yml similarity index 83% rename from .github/workflows/TestRunnerTiledSiracusaWithNeureka.yml rename to .github/workflows/_runner-siracusa-neureka-tiled.yml index 621d5d9976..1a596a0e91 100644 --- a/.github/workflows/TestRunnerTiledSiracusaWithNeureka.yml +++ b/.github/workflows/_runner-siracusa-neureka-tiled.yml @@ -1,6 +1,11 @@ -name: TestRunnerTiledSiracusaWithNeureka +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-siracusa-neureka-tiled + +"on": workflow_call: inputs: runner: @@ -29,21 +34,19 @@ on: default: false type: boolean memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string + required: false + default: "MiniMalloc" + type: string search-strategy: - required: false - default: "random-max" - type: string + 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 @@ -58,6 +61,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -76,4 +80,3 @@ jobs: 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 - \ No newline at end of file diff --git a/.github/workflows/TestRunnerTiledSiracusaSequential.yml b/.github/workflows/_runner-siracusa-tiled-sequential.yml similarity index 85% rename from .github/workflows/TestRunnerTiledSiracusaSequential.yml rename to .github/workflows/_runner-siracusa-tiled-sequential.yml index b4dc047003..6f88c624a9 100644 --- a/.github/workflows/TestRunnerTiledSiracusaSequential.yml +++ b/.github/workflows/_runner-siracusa-tiled-sequential.yml @@ -1,6 +1,11 @@ -name: TestRunnerTiledSiracusaSequential +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-siracusa-tiled + +"on": workflow_call: inputs: runner: @@ -34,7 +39,6 @@ on: type: string jobs: - test-runner-siracusa-tiled: runs-on: ${{ inputs.runner }} container: @@ -45,9 +49,13 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Install jq - run: apt-get install -y jq + run: | + export DEBIAN_FRONTEND=noninteractive + apt-get update -y + apt-get install -y jq - name: Cache ccache uses: actions/cache/restore@v4 with: @@ -69,4 +77,3 @@ jobs: done done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerTiledSiracusa.yml b/.github/workflows/_runner-siracusa-tiled.yml similarity index 89% rename from .github/workflows/TestRunnerTiledSiracusa.yml rename to .github/workflows/_runner-siracusa-tiled.yml index da0b8dcd75..c03bf71798 100644 --- a/.github/workflows/TestRunnerTiledSiracusa.yml +++ b/.github/workflows/_runner-siracusa-tiled.yml @@ -1,6 +1,11 @@ -name: TestRunnerTiledSiracusa +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-siracusa-tiled + +"on": workflow_call: inputs: runner: @@ -38,7 +43,6 @@ on: type: string jobs: - test-runner-siracusa-tiled: strategy: fail-fast: false @@ -53,6 +57,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -71,4 +76,3 @@ jobs: 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 - \ No newline at end of file diff --git a/.github/workflows/TestRunnerSiracusa.yml b/.github/workflows/_runner-siracusa.yml similarity index 84% rename from .github/workflows/TestRunnerSiracusa.yml rename to .github/workflows/_runner-siracusa.yml index edf3adfce5..28fa751b72 100644 --- a/.github/workflows/TestRunnerSiracusa.yml +++ b/.github/workflows/_runner-siracusa.yml @@ -1,6 +1,11 @@ -name: TestRunnerSiracusa +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-siracusa + +"on": workflow_call: inputs: runner: @@ -27,6 +32,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -46,4 +52,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerTiledSnitchSequential.yml b/.github/workflows/_runner-snitch-tiled-sequential.yml similarity index 79% rename from .github/workflows/TestRunnerTiledSnitchSequential.yml rename to .github/workflows/_runner-snitch-tiled-sequential.yml index 9a56172f96..2b9f2d0a27 100644 --- a/.github/workflows/TestRunnerTiledSnitchSequential.yml +++ b/.github/workflows/_runner-snitch-tiled-sequential.yml @@ -1,6 +1,11 @@ -name: TestRunnerTiledSnitchSequential +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-snitch-tiled-sequential + +"on": workflow_call: inputs: runner: @@ -21,20 +26,18 @@ on: default: "L2" type: string memory-allocation-strategy: - required: false - default: "MiniMalloc" - type: string + required: false + default: "MiniMalloc" + type: string search-strategy: - required: false - default: "random-max" - type: string + required: false + default: "random-max" + type: string simulators: required: true type: string - jobs: - test-runner-snitch-tiled: runs-on: ${{ inputs.runner }} container: @@ -45,9 +48,13 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Install jq - run: apt-get install -y jq + run: | + export DEBIAN_FRONTEND=noninteractive + apt-get update -y + apt-get install -y jq - name: Cache ccache uses: actions/cache/restore@v4 with: @@ -73,4 +80,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/TestRunnerSnitch.yml b/.github/workflows/_runner-snitch.yml similarity index 84% rename from .github/workflows/TestRunnerSnitch.yml rename to .github/workflows/_runner-snitch.yml index 302b21656a..0559b7b6f8 100644 --- a/.github/workflows/TestRunnerSnitch.yml +++ b/.github/workflows/_runner-snitch.yml @@ -1,6 +1,11 @@ -name: TestRunnerSnitch +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-snitch + +"on": workflow_call: inputs: runner: @@ -17,7 +22,7 @@ on: type: number simulators: required: true - type: string + type: string jobs: test-runner-snitch: @@ -30,6 +35,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Cache ccache uses: actions/cache/restore@v4 @@ -53,4 +59,4 @@ jobs: done fi done - shell: bash \ No newline at end of file + shell: bash diff --git a/.github/workflows/TestRunnerSoftHier.yml b/.github/workflows/_runner-softhier.yml similarity index 81% rename from .github/workflows/TestRunnerSoftHier.yml rename to .github/workflows/_runner-softhier.yml index 49ba951c7e..445f55114a 100644 --- a/.github/workflows/TestRunnerSoftHier.yml +++ b/.github/workflows/_runner-softhier.yml @@ -1,6 +1,11 @@ -name: TestRunnerSoftHier +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: _runner-softhier + +"on": workflow_call: inputs: runner: @@ -24,6 +29,7 @@ jobs: with: submodules: recursive - name: Build Deeploy + shell: bash run: pip install -e . - name: Run Test run: | @@ -37,4 +43,3 @@ jobs: fi done shell: bash - \ No newline at end of file diff --git a/.github/workflows/_select-env.yml b/.github/workflows/_select-env.yml new file mode 100644 index 0000000000..e8a77ee9d8 --- /dev/null +++ b/.github/workflows/_select-env.yml @@ -0,0 +1,48 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: _select-env +"on": + workflow_call: + inputs: + docker_image_deeploy: + type: string + required: true + outputs: + image: + value: ${{ jobs.select.outputs.image }} + runner: + value: ${{ jobs.select.outputs.runner }} + +jobs: + select: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.set-docker-image.outputs.image }} + runner: ${{ steps.set-runner.outputs.runner }} + steps: + - id: set-docker-image + shell: bash + run: | + if [[ -n "${{ inputs.docker_image_deeploy }}" ]]; then + IMAGE="${{ inputs.docker_image_deeploy }}" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + TAG_NAME="${GITHUB_REF##refs/tags/}" + IMAGE="ghcr.io/pulp-platform/deeploy:${TAG_NAME}" + elif [[ "${{ github.ref_name }}" == "main" ]]; then + IMAGE="ghcr.io/pulp-platform/deeploy:main" + else + IMAGE="ghcr.io/pulp-platform/deeploy:devel" + fi + echo "image=${IMAGE}" >> "$GITHUB_OUTPUT" + + - id: set-runner + shell: bash + run: | + if [[ "${{ github.repository }}" == "pulp-platform/Deeploy" ]]; then + echo "runner=self-hosted" >> "$GITHUB_OUTPUT" + else + echo "runner=ubuntu-latest" >> "$GITHUB_OUTPUT" + fi diff --git a/.github/workflows/ci-deeploy-testing.yml b/.github/workflows/ci-deeploy-testing.yml new file mode 100644 index 0000000000..1535951254 --- /dev/null +++ b/.github/workflows/ci-deeploy-testing.yml @@ -0,0 +1,78 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# 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: testTypeInferenceDifferentTypes + 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: testTypeInferenceDifferentTypes + 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: testTypeInferenceDifferentTypes + 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 new file mode 100644 index 0000000000..d57c65581f --- /dev/null +++ b/.github/workflows/ci-deeploy.yml @@ -0,0 +1,238 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Deeploy + +"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 }} + + build-deeploy: + 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 . + + deeploy-memory-allocation: + 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 testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=75000 --memAllocStrategy=MiniMalloc + python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=60000 --memAllocStrategy=MiniMalloc --shouldFail + python testMVP.py -t Tests/CCT/CCT_1_16_16_8 -p Siracusa --defaultMemLevel=L2 --l1=64000 --l2=90000 --memAllocStrategy=TetrisRandom + python testMVP.py -t Tests/CCT/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/simpleRegression -p QEMU-ARM + python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p Siracusa + python deeployStateEqualityTest.py -t ./Tests/simpleRegression -p MemPool + python deeployStateEqualityTest.py -t ./Tests/simpleRegression -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/simpleRegression -p QEMU-ARM + python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p Siracusa + python testMemoryLevelExtension.py -t ./Tests/simpleRegression -p MemPool + python testMemoryLevelExtension.py -t ./Tests/simpleRegression -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/simpleRegression + python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN + python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul + python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool + python testTilerExtension.py -p Siracusa -t ./Tests/simpleRegression --l1 2000 --shouldFail + python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN --l1 2000 --shouldFail + python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul --l1 2000 --shouldFail + python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool --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/simpleRegression + python testTilerExtension.py -p Siracusa -t ./Tests/simpleCNN + python testTilerExtension.py -p Siracusa -t ./Tests/miniMobileNet + python testTilerExtension.py -p Siracusa -t ./Tests/miniMobileNetv2 + python testTilerExtension.py -p Siracusa -t ./Tests/testMatMul + python testTilerExtension.py -p Siracusa -t ./Tests/testMaxPool + + 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/simpleRegression + python testPrintInputOutputTransformation.py -p Siracusa -t ./Tests/simpleRegression + python testDebugPrintPass.py -p Generic -t ./Tests/simpleRegression + + 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 diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml new file mode 100644 index 0000000000..3cab31bf3c --- /dev/null +++ b/.github/workflows/ci-lint.yml @@ -0,0 +1,108 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Lint & Licenses + +"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 }} + + linting: + 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 . --extra-index-url=https://pypi.ngc.nvidia.com + pip install -r requirements-dev.txt + - name: Format Python + shell: bash + run: | + yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . + - name: Format Python Imports + shell: bash + run: | + isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c + autoflake --quiet -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . + - name: Format C + shell: bash + run: | + python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts + - name: Format YAML + shell: bash + run: | + yamllint . + - name: Check Python Licenses + shell: bash + run: | + missing_py=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.py" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude "run_clang_format.py" . || true) + if [[ -n "$missing_py" ]]; then + echo "Missing SPDX in Python files:"; echo "$missing_py"; exit 1; fi + - name: Check C Licenses + shell: bash + run: | + missing_c=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.c" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true) + if [[ -n "$missing_c" ]]; then + echo "Missing SPDX in C files:"; echo "$missing_c"; exit 1; fi + - name: Check C Header Licenses + shell: bash + run: | + missing_h=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.h" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true) + if [[ -n "$missing_h" ]]; then + echo "Missing SPDX in headers:"; echo "$missing_h"; exit 1; fi + - name: Check YAML Licenses + shell: bash + run: | + missing_yaml=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.yaml" --include="*.yml" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true) + if [[ -n "$missing_yaml" ]]; then + echo "Missing SPDX in YAML files:"; echo "$missing_yaml"; exit 1; fi + - name: Check CMake Licenses + shell: bash + run: | + missing_cmake=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.cmake" --include="CMakeLists.txt" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true) + if [[ -n "$missing_cmake" ]]; then + echo "Missing SPDX in CMake files:"; echo "$missing_cmake"; exit 1; fi diff --git a/.github/workflows/ci-platform-chimera.yml b/.github/workflows/ci-platform-chimera.yml new file mode 100644 index 0000000000..6674f40505 --- /dev/null +++ b/.github/workflows/ci-platform-chimera.yml @@ -0,0 +1,41 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Chimera + +"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 }} + + chimera-kernels: + needs: select-env + uses: ./.github/workflows/_runner-chimera.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + simulators: | + gvsoc diff --git a/.github/workflows/ci-platform-cortexm.yml b/.github/workflows/ci-platform-cortexm.yml new file mode 100644 index 0000000000..d5a2da1dc8 --- /dev/null +++ b/.github/workflows/ci-platform-cortexm.yml @@ -0,0 +1,59 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Cortex-M + +"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 }} + + cortexm-kernels: + needs: select-env + uses: ./.github/workflows/_runner-cortexm.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + MultIO + test1DPad + test2DPad + testMatMul + testMatMulAdd + testMaxPool + testRQConv + testReduceSum + testReduceMean + testSlice + + cortexm-models: + needs: select-env + uses: ./.github/workflows/_runner-cortexm.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + simpleRegression + WaveFormer diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml new file mode 100644 index 0000000000..1e2b13b251 --- /dev/null +++ b/.github/workflows/ci-platform-generic.yml @@ -0,0 +1,97 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Generic + +"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 }} + + generic-kernels: + needs: select-env + uses: ./.github/workflows/_runner-generic.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + MultIO + test1DConvolution + test2DConvolution + test1DDWConvolution + test2DDWConvolution + test1DPad + test2DPad + testGEMM + testMatMul + testMatMulAdd + testMaxPool + testRQConv + testRQMatMul + testReduceSum + testReduceMean + testSlice + testRequantizedDWConv + test2DRequantizedConv + iSoftmax + testFloatAdder + testFloatGEMM + testFloat2DConvolution + testFloat2DConvolutionBias + testFloat2DConvolutionZeroBias + testFloatLayerNorm + testFloatDiv + testFloat2DDWConvolution + testFloat2DDWConvolutionBias + testFloat2DDWConvolutionZeroBias + testFloatRelu + testFloatMaxPool + testFloatMatmul + testFloatReshapeWithSkipConnection + testFloatSoftmax + testFloatTranspose + testFloatMul + Quant + Dequant + QuantizedLinear + + generic-models: + needs: select-env + uses: ./.github/workflows/_runner-generic.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + simpleRegression + WaveFormer + simpleCNN + ICCT + ICCT_ITA + ICCT_8 + ICCT_ITA_8 + miniMobileNet + miniMobileNetv2 + CCT/CCT_1_16_16_8 + testFloatDemoTinyViT diff --git a/.github/workflows/ci-platform-mempool.yml b/.github/workflows/ci-platform-mempool.yml new file mode 100644 index 0000000000..f2feed25b3 --- /dev/null +++ b/.github/workflows/ci-platform-mempool.yml @@ -0,0 +1,74 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Mempool + +"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 }} + + mempool-kernels: + needs: select-env + uses: ./.github/workflows/_runner-mempool.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + MultIO + test1DConvolution + test2DConvolution + test1DDWConvolution + test2DDWConvolution + test1DPad + test2DPad + testGEMM + testMatMul + testMatMulAdd + testMaxPool + testRQConv + testRQGEMM + testRQMatMul + testReduceSum + testReduceMean + testSlice + testRequantizedDWConv + test2DRequantizedConv + + mempool-models: + needs: select-env + uses: ./.github/workflows/_runner-mempool.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + simpleRegression + simpleCNN + ICCT + ICCT_ITA + ICCT_8 + ICCT_ITA_8 + miniMobileNet + miniMobileNetv2 diff --git a/.github/workflows/ci-platform-siracusa-neureka-tiled.yml b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml new file mode 100644 index 0000000000..31f1bcd1e9 --- /dev/null +++ b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml @@ -0,0 +1,146 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Siracusa + Neureka (Tiled) + +"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 }} + + siracusa-neureka-kernels-tiled-singlebuffer-L2: + needs: select-env + uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"testRequantizedLinear","L1":[16000]}, + {"name":"testPointwise","L1":[32000]}, + {"name":"testPointwiseConvBNReLU","L1":[32000]}, + {"name":"testPointwiseUnsignedWeights","L1":[32000]} + ] + num-cores: 8 + + siracusa-neureka-kernels-tiled-doublebuffer-L2: + needs: select-env + uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"testRequantizedLinear","L1":[16000]}, + {"name":"testPointwise","L1":[32000]}, + {"name":"testPointwiseConvBNReLU","L1":[32000]}, + {"name":"testPointwiseUnsignedWeights","L1":[32000]} + ] + num-cores: 8 + # double buffer enabled: + double-buffer: true + + siracusa-neureka-models-tiled-singlebuffer-L3: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - { name: "miniMobileNet", L1: [2000] } # LMACAN: 1000 leads to non-2d transfers in L3! + - { name: "Attention", L1: [2500] } + - { name: "Transformer", L1: [15000] } + - { name: "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 }} + + siracusa-neureka-models-tiled-doublebuffer-L3: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - { name: "miniMobileNet", L1: [2000] } # LMACAN note + - { name: "Attention", L1: [5000] } + - { name: "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 }} + + siracusa-neureka-kernels-tiled-singlebuffer-L2-wmem: + needs: select-env + uses: ./.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"testRequantizedLinear","L1":[16000]}, + {"name":"testPointwise","L1":[32000]}, + {"name":"testPointwiseConvBNReLU","L1":[32000]}, + {"name":"testPointwiseUnsignedWeights","L1":[32000]} + ] + num-cores: 8 + neureka-wmem: true + + siracusa-neureka-models-tiled-doublebuffer-L3-wmem: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - { name: "miniMobileNet", L1: [2000] } # LMACAN note + - { name: "Attention", L1: [3500] } + # - { name: "Transformer", L1: [30000] } + - { name: "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 }} diff --git a/.github/workflows/ci-platform-siracusa-tiled.yml b/.github/workflows/ci-platform-siracusa-tiled.yml new file mode 100644 index 0000000000..26cef57ffd --- /dev/null +++ b/.github/workflows/ci-platform-siracusa-tiled.yml @@ -0,0 +1,201 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Siracusa (Tiled) + +"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 }} + + siracusa-kernels-tiled-singlebuffer-L2: + needs: select-env + uses: ./.github/workflows/_runner-siracusa-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"testMatMul","L1":[64000,32000,16000]}, + {"name":"test2DRequantizedConv","L1":[8000,6000,4000]}, + {"name":"test2DRequantizedStriddedPaddedConv","L1":[600]}, + {"name":"testRequantizedDWConv","L1":[2561]}, + {"name":"iSoftmax","L1":[800,500,300]}, + {"name":"testConcat","L1":[32000,16000,8000]}, + {"name":"testRMSNorm","L1":[2048,1024,512]}, + {"name":"Hardswish","L1":[750]}, + {"name":"RQHardswish","L1":[750]}, + {"name":"testFloatGEMM","L1":[8000]}, + {"name":"testFloat2DConvolution","L1":[8000]}, + {"name":"testFloatLayerNorm","L1":[2000]}, + {"name":"testFloatRelu","L1":[2000]}, + {"name":"testFloatMaxPool","L1":[2000]}, + {"name":"testFloatMatmul","L1":[2000]}, + {"name":"testFloatSoftmax","L1":[4000]}, + {"name":"testFloatTranspose","L1":[2000]}, + {"name":"testFloatMul","L1":[2000]}, + {"name":"largeFloatAdd","L1":[220000]} + ] + num-cores: 8 + + siracusa-kernels-tiled-doublebuffer-L2: + needs: select-env + uses: ./.github/workflows/_runner-siracusa-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"testMatMul","L1":[64000,32000,16000]}, + {"name":"test2DRequantizedConv","L1":[8000,6000,5000]}, + {"name":"testRequantizedDWConv","L1":[5121]}, + {"name":"iSoftmax","L1":[1600,1000,600]}, + {"name":"testConcat","L1":[64000,32000,16000]}, + {"name":"testRMSNorm","L1":[4096,2048,1024]}, + {"name":"Hardswish","L1":[750]}, + {"name":"RQHardswish","L1":[800]}, + {"name":"testFloatGEMM","L1":[8000]}, + {"name":"testFloat2DConvolution","L1":[15000]}, + {"name":"testFloatLayerNorm","L1":[2000]}, + {"name":"testFloatRelu","L1":[2000]}, + {"name":"testFloatMaxPool","L1":[5000]}, + {"name":"testFloatMatmul","L1":[5000]}, + {"name":"testFloatSoftmax","L1":[8000]}, + {"name":"testFloatTranspose","L1":[2000]}, + {"name":"testFloatMul","L1":[2000]} + ] + num-cores: 8 + double-buffer: true + + siracusa-models-tiled-singlebuffer-L2: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - name: "simpleRegression" + L1: [45000, 30000, 15000] + - name: "miniMobileNet" + L1: [60000, 12000, 6000, 3000] + - name: "miniMobileNetv2" + L1: [60000, 16000, 12000, 8000] + - name: "Attention" + L1: [60000, 10000, 5000] + - name: "microLlama/microLlama1" + L1: [60000, 10000, 5000] + - name: "microLlama/microLlama8" + L1: [60000, 10000, 5000] + - name: "microLlama/microLlama8_parallel" + L1: [60000, 10000, 5000] + - name: "MLPerf/KeywordSpotting" + L1: [64000] + - name: "MLPerf/ImageClassification" + L1: [64000] + - name: "MLPerf/AnomalyDetection" + L1: [64000] + - name: "CCT/CCT_1_16_16_8" + L1: [64000] + - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8" + L1: [64000] + 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) }} + + siracusa-models-tiled-singlebuffer-L3: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - name: "simpleRegression" + L1: [45000, 30000, 16000] # SCHEREMO note + - name: "miniMobileNet" + L1: [60000, 12000, 6000] # SCHEREMO note + - name: "miniMobileNetv2" + L1: [60000, 16000, 12000, 8000] + - name: "Attention" + L1: [60000, 10000, 5000, 2500] + - name: "Transformer" + L1: [60000, 30000, 15000] + - name: "microLlama/microLlama1" + L1: [60000, 10000, 5000] + - name: "CCT/CCT_2_32_32_128" + L1: [128000] + - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_128" + L1: [64000] + 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 }} + + # TEMPORARILY DISABLE L3 TRANSFER DUE TO DRIVER BUG CAUSING SPORADIC CRASH + siracusa-models-tiled-doublebuffer-L3: + needs: select-env + strategy: + fail-fast: false + matrix: + test-data: + - name: "simpleRegression" + L1: [60000, 45000, 30000] + - name: "miniMobileNet" + L1: [60000, 24000, 12000, 6000] + - name: "miniMobileNetv2" + L1: [60000, 32000, 24000, 16000] + - name: "Attention" + L1: [60000, 20000, 10000, 5000] + - name: "Transformer" + L1: [60000, 30000, 15000] + - name: "microLlama/microLlama1" + L1: [60000, 20000, 10000] + - name: "microLlama/microLlama8" + L1: [60000, 20000, 10000] + - name: "microLlama/microLlama8_parallel" + L1: [60000, 20000, 10000] + - name: "CCT/CCT_2_32_32_128" + L1: [128000] + - name: "testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_128" + L1: [64000] + num-cores: [8] + double-buffer: [true] + 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) }} + double-buffer: ${{ matrix.double-buffer }} + default-memory-level: ${{ matrix.default-memory-level }} diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml new file mode 100644 index 0000000000..b1faeb863f --- /dev/null +++ b/.github/workflows/ci-platform-siracusa.yml @@ -0,0 +1,89 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Siracusa + +"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 }} + + siracusa-kernels: + needs: select-env + uses: ./.github/workflows/_runner-siracusa.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + MultIO + test1DPad + test2DPad + testMatMul + testMatMulAdd + testRequantizedDWConv + test2DRequantizedConv + iSoftmax + testConcat + testRMSNorm + trueIntegerDivSandwich + Hardswish + RQHardswish + testBacktracking + testFloatAdder + testFloatGEMM + testFloat2DConvolution + testFloatLayerNorm + testFloatRelu + testFloatMaxPool + testFloatMatmul + testFloatSoftmax + testFloatTranspose + testFloatMul + Quant + Dequant + testFloatReduceSum + testFloatSoftmaxGrad + testFloatSoftmaxCrossEntropy + testFloatSoftmaxCrossEntropyGrad + QuantizedLinear + num-cores: 8 + + siracusa-models: + needs: select-env + uses: ./.github/workflows/_runner-siracusa.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + simpleRegression + miniMobileNet + miniMobileNetv2 + Attention + MLPerf/KeywordSpotting + MLPerf/ImageClassification + MLPerf/AnomalyDetection + CCT/CCT_1_16_16_8 + testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8 + num-cores: 8 diff --git a/.github/workflows/ci-platform-snitch-tiled.yml b/.github/workflows/ci-platform-snitch-tiled.yml new file mode 100644 index 0000000000..75b8b63a54 --- /dev/null +++ b/.github/workflows/ci-platform-snitch-tiled.yml @@ -0,0 +1,50 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Snitch (Tiled) + +"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 }} + + snitch-kernels-tiled-singlebuffer-L2: + needs: select-env + uses: ./.github/workflows/_runner-snitch-tiled-sequential.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + tests-config: | + [ + {"name":"TestiNoNorm","L1":[5000,10000]}, + {"name":"TestAdderLarge","L1":[5000,10000]}, + {"name":"TestiSoftmaxLarge","L1":[5000,10000]}, + {"name":"testRQGEMM","L1":[2000,5000]}, + {"name":"testFloatSoftmax","L1":[2000,5000,10000]}, + {"name":"TestRQAdd","L1":[5000,10000]}, + {"name":"testFloatGEMM","L1":[2000,5000,10000]}, + {"name":"testFloatGEMMtransB","L1":[2000,5000,10000]} + ] + simulators: | + gvsoc diff --git a/.github/workflows/ci-platform-snitch.yml b/.github/workflows/ci-platform-snitch.yml new file mode 100644 index 0000000000..73076c66ab --- /dev/null +++ b/.github/workflows/ci-platform-snitch.yml @@ -0,0 +1,51 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • Snitch + +"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 }} + + snitch-kernels: + needs: select-env + uses: ./.github/workflows/_runner-snitch.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder + iSoftmax + TestiNoNorm + TestAdderLarge + TestiSoftmaxLarge + testMatMul + testRQGEMM + TestRQAdd + testRQGEMMTransB + testFloatSoftmax + num-cores: 9 + simulators: | + gvsoc diff --git a/.github/workflows/ci-platform-softhier.yml b/.github/workflows/ci-platform-softhier.yml new file mode 100644 index 0000000000..6e4921c809 --- /dev/null +++ b/.github/workflows/ci-platform-softhier.yml @@ -0,0 +1,39 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: CI • SoftHier + +"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 }} + + softhier-kernels: + needs: select-env + uses: ./.github/workflows/_runner-softhier.yml + with: + runner: ${{ needs.select-env.outputs.runner }} + docker-image: ${{ needs.select-env.outputs.image }} + test-names: | + Adder diff --git a/.github/workflows/BuildDockerDeeploy.yml b/.github/workflows/docker-build-deeploy.yml similarity index 88% rename from .github/workflows/BuildDockerDeeploy.yml rename to .github/workflows/docker-build-deeploy.yml index 34bd55d8ee..e75d56fb02 100644 --- a/.github/workflows/BuildDockerDeeploy.yml +++ b/.github/workflows/docker-build-deeploy.yml @@ -1,12 +1,17 @@ -name: BuildDockerDeeploy +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: Docker • Build Deeploy Container + +"on": workflow_dispatch: inputs: docker_image_toolchain: - description: 'Deeploy Toolchain Image to use' + description: "Deeploy Toolchain Image to use" required: false - default: 'ghcr.io/pulp-platform/deeploy-toolchain:latest' + default: "ghcr.io/pulp-platform/deeploy-toolchain:latest" jobs: prepare: @@ -34,7 +39,7 @@ jobs: build-deeploy: name: Build Deploy Image - needs: [ prepare ] + needs: [prepare] runs-on: ${{ matrix.runner }} outputs: digest-amd64: ${{ steps.digest.outputs.digest-amd64 }} @@ -89,7 +94,7 @@ jobs: run: | echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV} env: - OWNER: '${{ github.repository_owner }}' + OWNER: "${{ github.repository_owner }}" - name: Build and push final deploy image id: build @@ -112,7 +117,7 @@ jobs: merge-deeploy-images: name: Merge Deeploy Images runs-on: ubuntu-latest - needs: [ prepare, build-deeploy ] + needs: [prepare, build-deeploy] steps: - name: GHCR Log-in uses: docker/login-action@v3 @@ -125,7 +130,7 @@ jobs: run: | echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV} env: - OWNER: '${{ github.repository_owner }}' + OWNER: "${{ github.repository_owner }}" - name: Merge Deeploy Images uses: Noelware/docker-manifest-action@v1 @@ -136,4 +141,4 @@ jobs: tags: | ghcr.io/${{ env.OWNER_LC }}/deeploy:latest, ghcr.io/${{ env.OWNER_LC }}/deeploy:${{ needs.prepare.outputs.docker_tag }} - push: true \ No newline at end of file + push: true diff --git a/.github/workflows/BuildDockerToolchain.yml b/.github/workflows/docker-build-toolchain.yml similarity index 90% rename from .github/workflows/BuildDockerToolchain.yml rename to .github/workflows/docker-build-toolchain.yml index 03f9226288..6509fefa67 100644 --- a/.github/workflows/BuildDockerToolchain.yml +++ b/.github/workflows/docker-build-toolchain.yml @@ -1,6 +1,11 @@ -name: BuildDockerToolchain +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: Docker • Build Toolchain Container + +"on": workflow_dispatch: jobs: @@ -29,7 +34,7 @@ jobs: build-toolchain: name: Build Deeploy Toolchain Image - needs: [ prepare ] + needs: [prepare] runs-on: ${{ matrix.runner }} outputs: digest-amd64: ${{ steps.digest.outputs.digest-amd64 }} @@ -83,7 +88,7 @@ jobs: run: | echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV} env: - OWNER: '${{ github.repository_owner }}' + OWNER: "${{ github.repository_owner }}" - name: Build and push toolchain image id: build @@ -102,7 +107,7 @@ jobs: merge-toolchain-images: name: Merge Deeploy Toolchain Images runs-on: ubuntu-latest - needs: [ prepare, build-toolchain ] + needs: [prepare, build-toolchain] steps: - name: GHCR Log-in uses: docker/login-action@v3 @@ -115,7 +120,7 @@ jobs: run: | echo "OWNER_LC=${OWNER,,}" >>${GITHUB_ENV} env: - OWNER: '${{ github.repository_owner }}' + OWNER: "${{ github.repository_owner }}" - name: Merge Toolchain Images uses: Noelware/docker-manifest-action@v1 @@ -126,4 +131,4 @@ jobs: tags: | ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:latest, ghcr.io/${{ env.OWNER_LC }}/deeploy-toolchain:${{ needs.prepare.outputs.docker_tag }} - push: true \ No newline at end of file + push: true diff --git a/.github/workflows/infra-generate-ccache.yml b/.github/workflows/infra-generate-ccache.yml new file mode 100644 index 0000000000..0428a8333f --- /dev/null +++ b/.github/workflows/infra-generate-ccache.yml @@ -0,0 +1,50 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Infrastructure • Generate CCache + +"on": + workflow_dispatch: + inputs: + docker_image_deeploy: + description: "Deeploy Image to use" + required: false + default: "ghcr.io/pulp-platform/deeploy:devel" + schedule: + # Runs the workflow on the default branch every day at 1AM CET to keep the cache fresh + - cron: "0 1 * * *" + +jobs: + generate-ccache: + runs-on: ubuntu-latest + container: + image: ${{ github.event.inputs.docker_image_deeploy || 'ghcr.io/pulp-platform/deeploy:devel' }} + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + with: + submodules: recursive + - 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/Adder + python testRunner_mempool.py -t ./Tests/Adder + python testRunner_cortexm.py -t ./Tests/Adder + python testRunner_snitch.py -t ./Tests/Adder + python testRunner_tiled_snitch.py -t ./Tests/Adder + python testRunner_siracusa.py -t ./Tests/Adder + python testRunner_tiled_siracusa.py -t ./Tests/Adder + python testRunner_tiled_siracusa_w_neureka.py -t ./Tests/Adder + python testRunner_chimera.py -t ./Tests/Adder + - name: Clean and Upload CCache + uses: actions/cache@v4 + with: + path: /app/.ccache + key: ccache-ci diff --git a/.github/workflows/documentation.yml b/.github/workflows/infra-generate-documentation.yml similarity index 78% rename from .github/workflows/documentation.yml rename to .github/workflows/infra-generate-documentation.yml index ddd2c8a5c5..91e02c4b95 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/infra-generate-documentation.yml @@ -1,7 +1,16 @@ -name: documentation +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 -on: +--- +name: Infrastructure • Generate Documentation + +"on": push: + branches: + - "**" + tags: + - "v*.*.*" pull_request: workflow_dispatch: diff --git a/.gitlab/issue_templates/issue_template.md b/.gitlab/issue_templates/issue_template.md deleted file mode 100644 index 92cae8b04d..0000000000 --- a/.gitlab/issue_templates/issue_template.md +++ /dev/null @@ -1,24 +0,0 @@ -## Summary - -Give a *short* description of the problem, at most two paragraphs. - -## Steps to reproduce - -If possible create an example project that exhibits the problematic behaviour and reference it here. Please be as specific as possible. - -## Bug Behaviour - -Describe what is happening in your minimal example. - -## Expected Behaviour - -Describe what you expect to happen. - -## Relevant logs and/or screenshots - -If available, paste any relevant logs - use code blocks (```) to format console output, logs, and code, as -it's very hard to read otherwise. - -## Possible fixes - -If you can, link to the line of code that might be responsible for the problem. diff --git a/.gitlab/merge_request_templates/MRTemplate.md b/.gitlab/merge_request_templates/MRTemplate.md deleted file mode 100644 index f5321172a1..0000000000 --- a/.gitlab/merge_request_templates/MRTemplate.md +++ /dev/null @@ -1,19 +0,0 @@ -# Changelog - -Describe the intent of your merge request here. - -## Added - -## Changed - -## Fixed - - -## PR Merge Checklist - -1. [ ] Is your PR rebased on the latest `devel` commit and pointing to `devel`? -2. [ ] Was your PR reviewed and accepted? -3. [ ] Does your latest pipeline pass? -4. [ ] Are all dependencies merged onto their respective `main` branches? -5. [ ] Did you reset all .gitmodules URLs to point to the `deeploy` group? -6. [ ] Did you check in the latest commits for all dependencies available on their `main` branches? diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 799faa5dbe..6525fdda8d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,32 +1,71 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks -exclude: .*third_party.* - -# By default, all hooks will be installed as pre-push -default_stages: [pre-push] +--- +exclude: | + (?x)^( + .*third_party.* + | .*install.* + | .*toolchain.* + | .*TEST_.* + | .*TestFiles.* + | .*runtime.* + | .*\.git.* + ) repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-added-large-files + name: Check for added large files + - id: trailing-whitespace + name: Check for trailing whitespace + - repo: local + hooks: + - id: check-licenses + name: Check SPDX License Headers + entry: bash -c 'make check-licenses' + language: system + pass_filenames: false + stages: [pre-commit, pre-merge-commit, pre-push, manual] + - repo: https://github.com/google/yapf + rev: v0.43.0 hooks: - - id: check-added-large-files -- repo: https://github.com/PyCQA/autoflake + - id: yapf + name: Autoformat Python Files + args: ["--in-place", "--parallel"] + stages: [pre-commit, pre-merge-commit, pre-push, manual] + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + name: Autoformat Python Imports + args: ["--quiet"] + stages: [pre-commit, pre-merge-commit, pre-push, manual] + - repo: https://github.com/PyCQA/autoflake rev: v2.3.0 hooks: - - id: autoflake + - id: autoflake + name: Remove Unused Python Imports args: - - "--remove-all-unused-imports" - - "--ignore-init-module-imports" - - "--in-place" -- repo: https://github.com/google/yapf - rev: v0.33.0 + - "--remove-all-unused-imports" + - "--ignore-init-module-imports" + - "--in-place" + stages: [pre-commit, pre-merge-commit, pre-push, manual] + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v15.0.7 hooks: - - id: yapf - args: - - "--in-place" - - "--parallel" -- repo: https://github.com/pycqa/isort - rev: 5.12.0 + - id: clang-format + name: Autoformat C/C++ Files + args: ["-i"] + stages: [pre-commit, pre-merge-commit, pre-push, manual] + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.33.0 hooks: - - id: isort - name: isort (python) + - id: yamllint + name: Lint YAML Files + stages: [pre-commit, pre-merge-commit, pre-push, manual] diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 1874c6aee9..7fe57401ba 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,12 +1,12 @@ { - "configurations": [ - { - "name": "cMake", - "configurationProvider": "ms-vscode.cmake-tools", - "compileCommands": [ - "${workspaceFolder}/DeeployTest/TEST_RECENT/build/compile_commands.json" - ] - } - ], - "version": 4 + "configurations": [ + { + "name": "cMake", + "configurationProvider": "ms-vscode.cmake-tools", + "compileCommands": [ + "${workspaceFolder}/DeeployTest/TEST_RECENT/build/compile_commands.json" + ] + } + ], + "version": 4 } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 09ee03fed4..f889ab29d1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,89 +1,91 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Deeploy Generate Untiled", - "type": "debugpy", - "request": "launch", - "program": "generateNetwork.py", - "console": "integratedTerminal", - "cwd": "${workspaceFolder}/DeeployTest", - "justMyCode": false, - "args": "-p${input:platformUntiled} -t${input:model} ${input:additionalArgsUntiled}" + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Deeploy Generate Untiled", + "type": "debugpy", + "request": "launch", + "program": "generateNetwork.py", + "console": "integratedTerminal", + "cwd": "${workspaceFolder}/DeeployTest", + "justMyCode": false, + "args": + "-p${input:platformUntiled} -t${input:model} ${input:additionalArgsUntiled}" + }, + { + "name": "Deeploy Generate Tiled", + "type": "debugpy", + "request": "launch", + "program": "testMVP.py", + "console": "integratedTerminal", + "cwd": "${workspaceFolder}/DeeployTest", + "justMyCode": false, + "args": + "-p${input:platformTiled} -t${input:model} ${input:additionalArgsTiled}" + } + ], + "inputs": [ + { + "id": "platformUntiled", + "type": "pickString", + "description": "Problem", + "options": [ + "QEMU-ARM", + "Generic", + "MemPool", + "Apollo3", + "Apollo4", + "Snitch", + "Siracusa" + ], + "default": "Generic" + }, + { + "id": "platformTiled", + "type": "pickString", + "description": "Problem", + "options": [ + "Snitch", + "Siracusa", + "Siracusa_w_neureka" + ], + "default": "Siracusa" + }, + { + "id": "model", + "type": "command", + "command": "extension.commandvariable.file.pickFile", + "args": { + "description": "Select ONNX File", + "include": "**/*.onnx", + "display": "transform", + "fromFolder": { + "fixed": "${workspaceFolder}/DeeployTest/Tests" }, - { - "name": "Deeploy Generate Tiled", - "type": "debugpy", - "request": "launch", - "program": "testMVP.py", - "console": "integratedTerminal", - "cwd": "${workspaceFolder}/DeeployTest", - "justMyCode": false, - "args": "-p${input:platformTiled} -t${input:model} ${input:additionalArgsTiled}" - } - ], - "inputs": [ - { - "id": "platformUntiled", - "type": "pickString", - "description": "Problem", - "options": [ - "QEMU-ARM", - "Generic", - "MemPool", - "Apollo3", - "Apollo4", - "Snitch", - "Siracusa" - ], - "default": "Generic" - }, - { - "id": "platformTiled", - "type": "pickString", - "description": "Problem", - "options": [ - "Snitch", - "Siracusa", - "Siracusa_w_neureka" - ], - "default": "Siracusa" - }, - { - "id": "model", - "type": "command", - "command": "extension.commandvariable.file.pickFile", - "args": { - "description": "Select ONNX File", - "include": "**/*.onnx", - "display": "transform", - "fromFolder": { - "fixed": "${workspaceFolder}/DeeployTest/Tests" - }, - "labelTransform": { - "text": "${fileDirname}", - "find": ".*[\\/]", - "replace": "" - }, - "valueTransform": { - "text": "${fileDirname}" - } - } - }, - { - "id": "additionalArgsUntiled", - "type": "promptString", - "description": "Additional Arguments", - "default": "-v" + "labelTransform": { + "text": "${fileDirname}", + "find": ".*[\\/]", + "replace": "" }, - { - "id": "additionalArgsTiled", - "type": "promptString", - "description": "Additional Arguments", - "default": "-v --doublebuffer" + "valueTransform": { + "text": "${fileDirname}" } - ] + } + }, + { + "id": "additionalArgsUntiled", + "type": "promptString", + "description": "Additional Arguments", + "default": "-v" + }, + { + "id": "additionalArgsTiled", + "type": "promptString", + "description": "Additional Arguments", + "default": "-v --doublebuffer" + } + ] } \ No newline at end of file diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000000..2b1471b42f --- /dev/null +++ b/.yamllint @@ -0,0 +1,33 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +--- +extends: default + +rules: + line-length: disable + indentation: + spaces: 2 + indent-sequences: consistent + braces: + forbid: false + min-spaces-inside: 0 + max-spaces-inside: 2 + comments: + min-spaces-from-content: 1 + + +ignore: + # Ignore all files in third_party + - "**/third_party/" + # Ignore all files in runtime + - "**/runtime/" + # Ignore all files in TEST_* + - "**/TEST_*/" + # Ignore all files in install + - "**/install/" + # Ignore all files in toolchain + - "**/toolchain/" + # Ignore all files in .git + - "**/.git/**" diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9764f227..4a86155168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,12 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Split CI Workflows by Platform and Task, Improve Formatting and Linting Reliability [#108](https://github.com/pulp-platform/Deeploy/pull/108) +- Refactor tiling code generation [#105](https://github.com/pulp-platform/Deeploy/pull/105) - Change order of typeMatching entries [#68](https://github.com/pulp-platform/Deeploy/pull/68) - Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) -- Refactor tiling code generation [#105](https://github.com/pulp-platform/Deeploy/pull/105) ### Added - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough @@ -28,6 +29,10 @@ This file contains the changelog for the Deeploy project. The changelog is divid - NetworkContext: `is_buffer()` - helper function that determines whether the string represents a name of a buffer - missing checks for environment variables - `_permuteHyperRectangle` helper function +- Added CI badges to the README +- Added YAML linting to CI +- Added missing license headers and C header include guards +- Extended the pre-commit hooks to remove trailing whitespace, check licenses, format and lint files ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -48,10 +53,14 @@ This file contains the changelog for the Deeploy project. The changelog is divid - in some functions, instead of passing the name of a buffer, the actual buffer is just passed - tile function allows overriding the optimizer with external tilingSolution and memoryMap - refactor of the permutation functions for clarity +- Split CI into multiple workflow files: one per platform, one for lint & license, one for general Deeploy tests, one for infrastructure, and two for Docker flows, improving maintainability and status reporting +- Extended CI to check license in cMake and YAML files +- Removed all trailing whitespace ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. +- Fix license CI check and prevent potential issues with `jq` installation ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/CMakeLists.txt b/CMakeLists.txt index 04a3121baf..0a144b04b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + cmake_minimum_required(VERSION 3.12) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -106,7 +110,7 @@ if(platform STREQUAL SoftHier) if(TOOLCHAIN STREQUAL GCC) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/softhier/toolchain_gcc.cmake) endif() - + include(${CMAKE_CURRENT_LIST_DIR}/cmake/softhier/softhier_gvsoc.cmake) project(deeploy LANGUAGES C ASM) diff --git a/Deeploy/AbstractDataTypes.py b/Deeploy/AbstractDataTypes.py index 6af502c0f7..7c3601c0e6 100644 --- a/Deeploy/AbstractDataTypes.py +++ b/Deeploy/AbstractDataTypes.py @@ -267,8 +267,8 @@ def partialOrderUpcast(cls, otherCls: Type[Immediate]) -> bool: @classmethod def checkValue(cls, value: Union[float, Iterable[float], np.ndarray], ctxt: Optional[_NetworkContext] = None): """ - This method tries to manually cast standard python's standard immediate float precision values - (64 bits) to an arbitrary FP representation and check if the new representation is close enough + This method tries to manually cast standard python's standard immediate float precision values + (64 bits) to an arbitrary FP representation and check if the new representation is close enough to the original value. """ _val_list = [] diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py index d1f74e43d0..3144659959 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py @@ -40,9 +40,9 @@ accessStr += "[" + f"print_iter_{idx}" + "]" if idx > 0: dimStr += "[" + f"{dim}" + "]" -formatSpecifier = "%*i" +formatSpecifier = "%*i" if "float" in bufferType.referencedType.typeName or "double" in bufferType.referencedType.typeName: - formatSpecifier = "%*.6f" + formatSpecifier = "%*.6f" %> printf("${nodeName} ${bufferName}: ${bufferType.referencedType.typeName}, ${bufferShape}, %p\\n", ${bufferName}); % for idx, dim in enumerate(bufferShape): diff --git a/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py b/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py index bc490f5abc..5d05ee0089 100644 --- a/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py @@ -48,15 +48,15 @@ % if A_batched: ref_${data_out}_${A} += ${M} * ${N}; % endif - + % if B_batched: ref_${data_out}_${B} += ${N} * ${O}; % endif - + % if C_batched: ref_${data_out}_${C} += ${M} * ${O}; % endif - + ref_${data_out}_${data_out} += ${M} * ${O}; } END_SINGLE_CORE diff --git a/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py b/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py index f21c538541..6e7758347c 100644 --- a/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py @@ -27,6 +27,6 @@ referenceTemplate = NodeTemplate(""" // FloatLayernorm (Name: ${nodeName}, Op: ${nodeOp}) - + SINGLE_CORE Layernorm_fp${data_in_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}(${data_in}, ${data_out}, ${weight}, ${bias}, ${epsilon}, ${size}, ${lastDimLength}); """) \ No newline at end of file diff --git a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py index 8458330fb0..eddde93446 100644 --- a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py @@ -37,7 +37,7 @@ ref_${data_out}_${data_in}, ${ch_im_in}, ${dim_im_in_x}, ${dim_im_in_y},${dim_kernel_x}, ${dim_kernel_y}, ${stride_x}, ${stride_y}, ref_${data_out}_${data_out} ); - + } END_SINGLE_CORE """) diff --git a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py index 4788c844ac..c7a6d6c714 100644 --- a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py @@ -29,7 +29,7 @@ <% y_offset_out = dim_im_out_ch*(pad_y*dim_im_out_y) x_offset_out = dim_im_out_ch*(pad_x) - width = dim_im_in_ch*dim_im_in_y + width = dim_im_in_ch*dim_im_in_y addoffsetOut = dim_im_out_ch * dim_im_out_y addoffsetIn = dim_im_in_ch * dim_im_in_y diff --git a/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py b/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py index d9579c3030..c797d406e6 100644 --- a/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py @@ -25,7 +25,7 @@ from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" -// Float ReduceSum (Name: ${nodeName}, Op: ${nodeOp}) +// Float ReduceSum (Name: ${nodeName}, Op: ${nodeOp}) BEGIN_SINGLE_CORE float32_t ${data_out}_accumulator = 0.0f; <% reduceLength = 1 diff --git a/Deeploy/Targets/Generic/Templates/QuantTemplate.py b/Deeploy/Targets/Generic/Templates/QuantTemplate.py index 817f90a04d..8633b90302 100644 --- a/Deeploy/Targets/Generic/Templates/QuantTemplate.py +++ b/Deeploy/Targets/Generic/Templates/QuantTemplate.py @@ -35,23 +35,23 @@ def __init__(self, templateStr): referenceTemplate = _QuantTemplate(""" // Quantization (Name: ${nodeName}, Op: ${nodeOp}) BEGIN_SINGLE_CORE - + for (uint32_t i=0; i<${size}; i++) { // quantization formula float32_t input_val = ${data_in}[i]; float32_t scaled_val = input_val * ${scale}; // Multiply instead of divide float32_t shifted_val = scaled_val + ${zero_point}; - + // Round to nearest integer int32_t quantized = (int32_t)(shifted_val + 0.5f * (shifted_val >= 0 ? 1 : -1)); - + // Clamp the value if (quantized < ${min_val}) quantized = ${min_val}; if (quantized > ${max_val}) quantized = ${max_val}; - + // Assign directly with explicit cast ${data_out}[i] = (${data_out_type.referencedType.typeName})quantized; - + } END_SINGLE_CORE """) diff --git a/Deeploy/Targets/Generic/Templates/SliceTemplate.py b/Deeploy/Targets/Generic/Templates/SliceTemplate.py index fa475e22dc..b0188bbf06 100644 --- a/Deeploy/Targets/Generic/Templates/SliceTemplate.py +++ b/Deeploy/Targets/Generic/Templates/SliceTemplate.py @@ -67,7 +67,7 @@ def alignToContext(self, ctxt: NetworkContext, for dim in data_in_shape[1:]: dimSteps.append(dimSteps[-1]//dim) %> -<% +<% transferSize = dimSteps[int(axes[-1])] %> <% diff --git a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py index c74b4da7ed..1d82e983d1 100644 --- a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py +++ b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: L3Dma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import math from typing import Dict, Tuple diff --git a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py index 0f2b77a03d..ee524849de 100644 --- a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py +++ b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: MchanDma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import math from typing import Dict, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py index 561ba49952..563639a90b 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py @@ -63,15 +63,15 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, for (uint32_t n=0; n<${batch}; ++n) { PULP_Conv2d_fp${data_in_type.referencedType.typeWidth}_fp${weight_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}_HWC( - ref_${data_out}_${data_in}, + ref_${data_out}_${data_in}, ${dim_im_in_y}, ${dim_im_in_x}, ${ch_im_in}, ${weight}, ${ch_im_out}, ${dim_kernel_y}, ${dim_kernel_x}, ${stride_y}, ${stride_x}, - ref_${data_out}_${data_out}, + ref_${data_out}_${data_out}, ${padding_y_top}, ${padding_y_bottom}, ${padding_x_left}, ${padding_x_right} ); - + ref_${data_out}_${data_in} += ${ch_im_in} * ${dim_im_in_x} * ${dim_im_in_y}; ref_${data_out}_${data_out} += ${ch_im_out} * ${dim_im_out_x} * ${dim_im_out_y}; @@ -84,24 +84,24 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, ${data_in_type.typeName} ref_${data_out}_${data_in} = ${data_in}; ${data_out_type.typeName} ref_${data_out}_${data_out} = ${data_out}; -for (uint32_t n=0; n<${batch}; ++n) { +for (uint32_t n=0; n<${batch}; ++n) { PULP_Conv2d_Im2Col_fp${data_in_type.referencedType.typeWidth}_fp${weight_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}_HWC( - ref_${data_out}_${data_in}, - ${dim_im_in_y}, - ${dim_im_in_x}, - ${ch_im_in}, - ${weight}, - ${ch_im_out}, - ${dim_kernel_y}, - ${dim_kernel_x}, - ${stride_y}, - ${stride_x}, - ref_${data_out}_${data_out}, - ${padding_y_top}, - ${padding_y_bottom}, - ${padding_x_left}, - ${padding_x_right}, - ${ctxtBuffer} + ref_${data_out}_${data_in}, + ${dim_im_in_y}, + ${dim_im_in_x}, + ${ch_im_in}, + ${weight}, + ${ch_im_out}, + ${dim_kernel_y}, + ${dim_kernel_x}, + ${stride_y}, + ${stride_x}, + ref_${data_out}_${data_out}, + ${padding_y_top}, + ${padding_y_bottom}, + ${padding_x_left}, + ${padding_x_right}, + ${ctxtBuffer} ); ref_${data_out}_${data_in} += ${ch_im_in} * ${dim_im_in_x} * ${dim_im_in_y}; diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py index eb017002ce..9f7fa4bc95 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py @@ -43,7 +43,7 @@ ${transA}, ${transB} ); - + ref_${data_out}_${A} += ${M} * ${N}; ref_${data_out}_${B} += ${N} * ${O}; ref_${data_out}_${C} += ${M} * ${O}; diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py index 05898ee16d..2040c85fef 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py @@ -28,12 +28,12 @@ referenceTemplate = NodeTemplate(""" // Float Layernorm (Name: ${nodeName}, Op: ${nodeOp}) PULP_Layernorm_fp${data_in_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}( - ${data_in}, - ${data_out}, - ${weight}, - ${bias}, - ${epsilon}, - ${size}, + ${data_in}, + ${data_out}, + ${weight}, + ${bias}, + ${epsilon}, + ${size}, ${lastDimLength} ); """) \ No newline at end of file diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py index bcbcd0aefa..cd6d17b01e 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py @@ -31,13 +31,13 @@ ${A_type.typeName} batch_A = ${A} + b * ${M} * ${N}; ${B_type.typeName} batch_B = ${B} + b * ${N} * ${O}; ${data_out_type.typeName} batch_out = ${data_out} + b * ${M} * ${O}; - + PULP_MatMul_fp32_fp32_fp32_unroll1x7( batch_A, - batch_B, + batch_B, batch_out, ${M}, - ${N}, + ${N}, ${O} ); } diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py index f1a01227ec..f32d98cf50 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py @@ -33,9 +33,9 @@ for (uint32_t n=0; n<${batch}; ++n) { PULP_MaxPool2d_fp${data_in_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}_HWC( - ref_${data_out}_${data_in}, + ref_${data_out}_${data_in}, ${dim_im_in_x}, ${dim_im_in_y}, ${ch_im_in}, - ${dim_kernel_x}, ${dim_kernel_y}, + ${dim_kernel_x}, ${dim_kernel_y}, ${stride_x}, ${stride_y}, ref_${data_out}_${data_out}, ${padding_y_top}, ${padding_y_bottom}, ${padding_x_left}, ${padding_x_right} diff --git a/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py b/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py index 4f3308d1f3..4d36a047af 100644 --- a/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py @@ -31,8 +31,8 @@ ${weight_type.typeName} ref_${weight} = ${weight}; ${grad_type.typeName} ref_${grad} = ${grad}; ${weight_type.typeName} ref_${weight_updated} = ${weight_updated}; - - float32_t learning_rate = ${lr}; + + float32_t learning_rate = ${lr}; for (uint32_t i=0; i<${size}; ++i) { ref_${weight_updated}[i] = ref_${weight}[i] - learning_rate * ref_${grad}[i]; diff --git a/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py b/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py index 9599aa1bf7..d81bda4bb9 100644 --- a/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py @@ -35,12 +35,12 @@ max_logit = ${logits}[i * ${num_classes} + j]; } } - + float32_t sum_exp = 0.0f; for (uint32_t j = 0; j < ${num_classes}; j++) { sum_exp += expf(${logits}[i * ${num_classes} + j] - max_logit); } - + for (uint32_t j = 0; j < ${num_classes}; j++) { // log_prob = logit - max_logit - log(sum_exp) ${log_prob}[i * ${num_classes} + j] = ${logits}[i * ${num_classes} + j] - max_logit - logf(sum_exp); @@ -63,6 +63,6 @@ } } } - + END_SINGLE_CORE """) diff --git a/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py b/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py index d0f4e220be..65cfdd94ba 100644 --- a/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py @@ -54,15 +54,15 @@ def alignToContext(self, ctxt: NetworkContext, int16_t ${nodeName}_chunk = (${int(M)} >> ${nodeName}_log2Core) + ((${int(M)} & (NUM_CORES-1))!=0); int16_t ${nodeName}_chunk_start = MIN(${nodeName}_chunk*${nodeName}_core_id, ${int(M)}); int16_t ${nodeName}_chunk_stop = MIN(${nodeName}_chunk_start + ${nodeName}_chunk, ${int(M)} + 1); - + int8_t* ref_${nodeName}_${A}; int8_t* ref_${nodeName}_${B}; int8_t* ref_${nodeName}_${data_out}; - + for(int b=0; b<${batch}; b++){ for (uint32_t i=${nodeName}_chunk_start; i<${nodeName}_chunk_stop; i++){ - + int8_t* ref_${nodeName}_${A} = ${A} + (b * ${M} * ${N}) + (i * ${N}); % if W_batched: int8_t* ref_${nodeName}_${B} = ${B} + (b * ${N} * ${O}); @@ -70,7 +70,7 @@ def alignToContext(self, ctxt: NetworkContext, int8_t* ref_${nodeName}_${B} = ${B}; % endif int8_t* ref_${nodeName}_${data_out} = ${data_out} + (b * ${M} * ${O}) + (i * ${O}); - + gemv_s8_s8_plp(ref_${nodeName}_${A}, NULL, ref_${nodeName}_${data_out}, ref_${nodeName}_${B}, ${mul}, ${C}, 1, ${log2D}, ${N}, ${O}, 1, 1); } } diff --git a/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py b/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py index 4cfd3d6f83..928b50e9e5 100644 --- a/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py @@ -78,7 +78,7 @@ def alignToContext(self, ctxt: NetworkContext, inSignage = "s" if signedI else "u" outSignage = "s" if signedO else "u" mul_int_immediate = int(mul_immediate) -add_int_immediate = int(add_immediate) +add_int_immediate = int(add_immediate) %> // UniformRequantShift (Name: ${nodeName}, Op: ${nodeOp}) diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py index 101a056644..66cfcd8211 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: LayernormTileConstraint.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Run Wang, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, List, Tuple import numpy as np diff --git a/Deeploy/Targets/Snitch/DMA/SnitchDma.py b/Deeploy/Targets/Snitch/DMA/SnitchDma.py index 6e2533697d..236448e426 100644 --- a/Deeploy/Targets/Snitch/DMA/SnitchDma.py +++ b/Deeploy/Targets/Snitch/DMA/SnitchDma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: SnitchDma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, Tuple from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer diff --git a/Deeploy/Targets/Snitch/Templates/AddTemplate.py b/Deeploy/Targets/Snitch/Templates/AddTemplate.py index f60462516c..3354bdfa4a 100644 --- a/Deeploy/Targets/Snitch/Templates/AddTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/AddTemplate.py @@ -54,5 +54,5 @@ def alignToContext(self, ctxt: NetworkContext, referenceTemplate = _SnitchAddTemplate(""" // Snitch Add (Name: ${nodeName}, Op: ${nodeOp}) -SnitchAdd(${data_in_1}, ${data_in_2}, ${data_out}, ${size}, ${offset}); +SnitchAdd(${data_in_1}, ${data_in_2}, ${data_out}, ${size}, ${offset}); """) diff --git a/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py b/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py index 5db62baacb..fdbc71e901 100644 --- a/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py @@ -1,11 +1,36 @@ +# ---------------------------------------------------------------------- +# +# File: FloatGemmTemplate.py +# +# Last edited: 03.06.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: +# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" uint32_t compute_num = snrt_cluster_compute_core_num(); - + % if transB: gemm_fp32_transB_opt(${M} / compute_num, ${O}, ${N}, ${A}, ${N} * compute_num, ${B}, ${N}, ${C}, ${O} * compute_num, ${data_out}, 1, 1 ); -% else: +% else: gemm_fp32_opt(${M} / compute_num, ${O}, ${N}, ${A}, ${N} * compute_num, ${B}, ${O}, ${C}, ${O} * compute_num, ${data_out}, 1, 1 ); %endif """) diff --git a/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py b/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py index 877c02fef0..15bce0a1d9 100644 --- a/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py @@ -50,7 +50,7 @@ def alignToContext(self, ctxt: NetworkContext, uint32_t compute_num = 1; //snrt_cluster_compute_core_num(); int32_t ldI = compute_num * ${input_samples}; int32_t batch_offset = ${seq_len} * ${input_samples}; - + // JUNGVI: This implementation is broken and has memory leak. if (snrt_hartid() == 0){ ${kernelName}(${data_in}, ${data_out}, ldI, batch_offset, batch_size, ${seq_len}, ${input_samples}); diff --git a/Deeploy/Targets/Snitch/Templates/GemmTemplate.py b/Deeploy/Targets/Snitch/Templates/GemmTemplate.py index 8bc0fee698..12fadbf577 100644 --- a/Deeploy/Targets/Snitch/Templates/GemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/GemmTemplate.py @@ -1,3 +1,28 @@ +# ---------------------------------------------------------------------- +# +# File: __init__.py +# +# Last edited: 03.06.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: +# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, List, Tuple from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation diff --git a/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py b/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py index 918690e4e0..c257c36d86 100644 --- a/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py @@ -1,3 +1,28 @@ +# ---------------------------------------------------------------------- +# +# File: RqGemmTemplate.py +# +# Last edited: 03.06.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: +# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, List, Tuple from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation diff --git a/Deeploy/Targets/Snitch/Templates/__init__.py b/Deeploy/Targets/Snitch/Templates/__init__.py index b9742821a6..cc12bda690 100644 --- a/Deeploy/Targets/Snitch/Templates/__init__.py +++ b/Deeploy/Targets/Snitch/Templates/__init__.py @@ -1 +1,26 @@ +# ---------------------------------------------------------------------- +# +# File: __init__.py +# +# Last edited: 03.06.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: +# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from . import * \ No newline at end of file diff --git a/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py index 99fdddd21a..58a4b5cb44 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: GemmTileConstraint.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, List, Tuple from Deeploy.AbstractDataTypes import PointerClass diff --git a/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py index 5feae3b206..6708273dfa 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: RqGemmTileConstraint.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import Dict, List, Tuple from Deeploy.AbstractDataTypes import PointerClass diff --git a/Deeploy/Targets/Snitch/__init__.py b/Deeploy/Targets/Snitch/__init__.py index b9742821a6..cc12bda690 100644 --- a/Deeploy/Targets/Snitch/__init__.py +++ b/Deeploy/Targets/Snitch/__init__.py @@ -1 +1,26 @@ +# ---------------------------------------------------------------------- +# +# File: __init__.py +# +# Last edited: 03.06.2024 +# +# Copyright (C) 2024, ETH Zurich and University of Bologna. +# +# Author: +# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from . import * \ No newline at end of file diff --git a/Deeploy/TilingExtension/AsyncDma.py b/Deeploy/TilingExtension/AsyncDma.py index ea1dd99edf..2b2bfef369 100644 --- a/Deeploy/TilingExtension/AsyncDma.py +++ b/Deeploy/TilingExtension/AsyncDma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: AsyncDma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import math from abc import ABC, abstractmethod from typing import Dict, List, Literal, Set, Tuple, Type diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py index 4aa0f03de9..b47aa5888a 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: TilingHoistingMixIn.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import math from typing import List, Mapping, Optional, Sequence, Tuple, Type, TypeVar, Union diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py index b09192c5b7..5dc9c11eeb 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py @@ -66,7 +66,7 @@ class TilingMetaInfo: """) _printLoopSetup = NodeTemplate(""" -StopTimer(); +StopTimer(); for (int ${profileIdxVar} = ${numTiles}[*${tileIdxPtr} -1]; ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; ${profileIdxVar}++){ """) diff --git a/DeeployTest/CMakeLists.txt b/DeeployTest/CMakeLists.txt index a48d6c8acb..6dad44829f 100644 --- a/DeeployTest/CMakeLists.txt +++ b/DeeployTest/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + include_directories(${GENERATED_SOURCE}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/DeeployTest/Platforms/Chimera/CMakeLists.txt b/DeeployTest/Platforms/Chimera/CMakeLists.txt index 6d3b0aa74e..ba583f44a8 100644 --- a/DeeployTest/Platforms/Chimera/CMakeLists.txt +++ b/DeeployTest/Platforms/Chimera/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/Generic/CMakeLists.txt b/DeeployTest/Platforms/Generic/CMakeLists.txt index 2a53f51c38..6c22e993c7 100644 --- a/DeeployTest/Platforms/Generic/CMakeLists.txt +++ b/DeeployTest/Platforms/Generic/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/MemPool/CMakeLists.txt b/DeeployTest/Platforms/MemPool/CMakeLists.txt index 0b4b94b031..8faa483dc4 100644 --- a/DeeployTest/Platforms/MemPool/CMakeLists.txt +++ b/DeeployTest/Platforms/MemPool/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/PULPOpen/CMakeLists.txt b/DeeployTest/Platforms/PULPOpen/CMakeLists.txt index 8810862885..6a0f685059 100644 --- a/DeeployTest/Platforms/PULPOpen/CMakeLists.txt +++ b/DeeployTest/Platforms/PULPOpen/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt b/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt index 9820396bd0..1e618207f1 100644 --- a/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt +++ b/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/Siracusa/CMakeLists.txt b/DeeployTest/Platforms/Siracusa/CMakeLists.txt index e42b250a71..1e9cee730f 100644 --- a/DeeployTest/Platforms/Siracusa/CMakeLists.txt +++ b/DeeployTest/Platforms/Siracusa/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/Snitch/CMakeLists.txt b/DeeployTest/Platforms/Snitch/CMakeLists.txt index 44568890de..568303b08a 100644 --- a/DeeployTest/Platforms/Snitch/CMakeLists.txt +++ b/DeeployTest/Platforms/Snitch/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/Platforms/SoftHier/CMakeLists.txt b/DeeployTest/Platforms/SoftHier/CMakeLists.txt index 22ebafc2f9..20797bed05 100644 --- a/DeeployTest/Platforms/SoftHier/CMakeLists.txt +++ b/DeeployTest/Platforms/SoftHier/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(ProjectId ${TESTNAME}) file(GLOB_RECURSE SOURCES diff --git a/DeeployTest/testDmas.py b/DeeployTest/testDmas.py index 6cca30e15d..c014b7676b 100644 --- a/DeeployTest/testDmas.py +++ b/DeeployTest/testDmas.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: testDmas.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import itertools import subprocess from typing import Tuple diff --git a/DeeployTest/testRunner_siracusa_l3dma.py b/DeeployTest/testRunner_siracusa_l3dma.py index 7507bf8ec9..f174cdd867 100644 --- a/DeeployTest/testRunner_siracusa_l3dma.py +++ b/DeeployTest/testRunner_siracusa_l3dma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: testRunner_siracusa_l3dma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import numpy as np diff --git a/DeeployTest/testRunner_siracusa_mchandma.py b/DeeployTest/testRunner_siracusa_mchandma.py index c16f584b21..8fe5fe6e9e 100644 --- a/DeeployTest/testRunner_siracusa_mchandma.py +++ b/DeeployTest/testRunner_siracusa_mchandma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: testRunner_siracusa_mchandma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import numpy as np diff --git a/DeeployTest/testRunner_snitch.py b/DeeployTest/testRunner_snitch.py index 49f51f96d0..a84d072a33 100644 --- a/DeeployTest/testRunner_snitch.py +++ b/DeeployTest/testRunner_snitch.py @@ -2,7 +2,7 @@ # # File: testRunner_snitch.py # -# Last edited: 23.04.2024 +# Last edited: 11.08.2025 # # Copyright (C) 2024, ETH Zurich and University of Bologna. # diff --git a/DeeployTest/testRunner_snitch_dma.py b/DeeployTest/testRunner_snitch_dma.py index 96e6542bb9..9fa432a6f4 100644 --- a/DeeployTest/testRunner_snitch_dma.py +++ b/DeeployTest/testRunner_snitch_dma.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: testRunner_snitch_dma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import numpy as np diff --git a/DeeployTest/testUtils/dmaUtils.py b/DeeployTest/testUtils/dmaUtils.py index f9722168d6..6b476ffb17 100644 --- a/DeeployTest/testUtils/dmaUtils.py +++ b/DeeployTest/testUtils/dmaUtils.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: dmaUtils.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import math from typing import Dict, List, Optional, Tuple, Type diff --git a/DeeployTest/testUtils/tilingUtils.py b/DeeployTest/testUtils/tilingUtils.py index 78a9bbcdd8..a25a50938d 100644 --- a/DeeployTest/testUtils/tilingUtils.py +++ b/DeeployTest/testUtils/tilingUtils.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: tilingUtils.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Moirtz Scherer, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from typing import List, Union from ortools.constraint_solver.pywrapcp import IntVar diff --git a/Makefile b/Makefile index bcbdc0f783..0ff8de1805 100644 --- a/Makefile +++ b/Makefile @@ -460,7 +460,7 @@ ${TOOLCHAIN_DIR}/softhier: rm ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/include/flex_alloc.h && \ rm ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/include/flex_runtime.h && \ mv ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/flex_memory_deeploy.ld ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/flex_memory.ld && \ - cp ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/deeploy_include/* ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/include + cp ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/deeploy_include/* ${TOOLCHAIN_DIR}/softhier/soft_hier/flex_cluster_sdk/runtime/include ${SOFTHIER_INSTALL_DIR}: ${TOOLCHAIN_DIR}/softhier cp -r ${TOOLCHAIN_DIR}/softhier ${SOFTHIER_INSTALL_DIR} && \ @@ -566,10 +566,61 @@ chimera-sdk: ${CHIMERA_SDK_INSTALL_DIR} .PHONY: docs clean-docs format format: - python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format -ir ./ scripts - autoflake -i -r --remove-all-unused-imports --ignore-init-module-imports --exclude "*/third_party/**" ./ - yapf -ipr -e "third_party/" -e "install/" -e "toolchain/" . - isort --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ + @echo "Formatting all relevant files..." + @echo " - Format Python Files" + @yapf -ipr -e "third_party/" -e "install/" -e "toolchain/" . + @echo " - Format Python Imports" + @isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ + @autoflake -i -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . + @echo " - Format C/C++ Files" + @python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format -ir ./ scripts + +lint: check-licenses + @echo "Linting all relevant files..." + @echo " - Lint Python Files" + @yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . + @echo " - Lint Python Imports" + @isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c + @autoflake --quiet -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . + @echo " - Lint C/C++ Files" + @python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts + @echo " - Lint YAML files" + @yamllint . + +check-licenses: + @echo "Checking SPDX license headers in all relevant files..." + @rc=0; \ + echo " - Check Python Files"; \ + missing_py=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.py" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude "run_clang_format.py" . || true); \ + if [ -n "$$missing_py" ]; then echo "$$missing_py"; rc=1; fi; \ + echo " - Check C Files"; \ + missing_c=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.c" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true); \ + if [ -n "$$missing_c" ]; then echo "$$missing_c"; rc=1; fi; \ + echo " - Check C Header Files"; \ + missing_h=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.h" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true); \ + if [ -n "$$missing_h" ]; then echo "$$missing_h"; rc=1; fi; \ + echo " - Check YAML Files"; \ + missing_yaml=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.yaml" --include="*.yml" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true); \ + if [ -n "$$missing_yaml" ]; then echo "$$missing_yaml"; rc=1; fi; \ + echo " - Check CMake Files"; \ + missing_cmake=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.cmake" --include="CMakeLists.txt" \ + --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ + --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ + --exclude-dir="runtime" . || true); \ + if [ -n "$$missing_cmake" ]; then echo "$$missing_cmake"; rc=1; fi; \ + exit $$rc docs: make -C docs html diff --git a/README.md b/README.md index 0e00125731..bbb5fdba0a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Documentation Status](https://img.shields.io/github/deployments/pulp-platform/Deeploy/github-pages?logo=readthedocs&logoColor=white&label=Docs )](https://pulp-platform.github.io/Deeploy/) -![CI](https://github.com/pulp-platform/Deeploy/actions/workflows/CI.yml/badge.svg?branch=devel) +[![CI](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml) ![Deeploy Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/BuildDockerDeeploy.yml/badge.svg) ![Toolchain Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/BuildDockerToolchain.yml/badge.svg) [![GitHub last commit](https://img.shields.io/github/last-commit/pulp-platform/Deeploy)](#) @@ -80,16 +80,15 @@ Now you can open the generated code in `DeeployTest/TEST_SIRACUSA/Tests/testMatM ## Supported Platforms -| **Platform** | **Hardware** | **Simulator** | -| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | -| **Generic CPU** | Your laptop CPU :) | Host | -| **CortexM Processors** | [Documentation](https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m4) | [QEMU](https://www.qemu.org/) | -| **MemPool + ITA** | [Mempool paper](https://arxiv.org/abs/2303.17742), [ITA paper](https://arxiv.org/abs/2307.03493) | [Banshee](https://github.com/pulp-platform/banshee) | -| **Siracusa** | [Siracusa paper](https://arxiv.org/abs/2312.14750) | [GVSoC](https://github.com/gvsoc/gvsoc) | -| **Snitch Cluster** | [Snitch paper](https://arxiv.org/abs/2002.10143) | [GVSoC](https://github.com/gvsoc/gvsoc) | -| **SoftHier** | [Repo](https://github.com/gvsoc/gvsoc/tree/soft_hier_release) | [GVSoC](https://github.com/gvsoc/gvsoc/tree/soft_hier_release) | -| **Chimera** | [Repo](https://github.com/pulp-platform/chimera) | [GVSoC](https://github.com/gvsoc/gvsoc) | - +| **Platform** | **Hardware** | **Simulator** | **CI Status** +| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | --------------- +| **Generic CPU** | Your laptop CPU :) | Host | [![CI • Generic](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-generic.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-generic.yml) +| **CortexM Processors** | [Documentation](https://www.arm.com/products/silicon-ip-cpu/cortex-m/cortex-m4) | [QEMU](https://www.qemu.org/) | [![CI • Cortex-M](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-cortexm.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-cortexm.yml) +| **MemPool + ITA** | [Mempool paper](https://arxiv.org/abs/2303.17742), [ITA paper](https://arxiv.org/abs/2307.03493) | [Banshee](https://github.com/pulp-platform/banshee) | [![CI • Mempool](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-mempool.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-mempool.yml) +| **Siracusa** | [Siracusa paper](https://arxiv.org/abs/2312.14750) | [GVSoC](https://github.com/gvsoc/gvsoc) | [![CI • Siracusa](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa.yml) [![CI • Siracusa (Tiled)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa-tiled.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa-tiled.yml) [![CI • Siracusa + Neureka (Tiled)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa-neureka-tiled.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-siracusa-neureka-tiled.yml) +| **Snitch Cluster** | [Snitch paper](https://arxiv.org/abs/2002.10143) | [GVSoC](https://github.com/gvsoc/gvsoc) | [![CI • Snitch](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-snitch.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-snitch.yml) [![CI • Snitch (Tiled)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-snitch-tiled.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-snitch-tiled.yml) +| **SoftHier** | [Repo](https://github.com/gvsoc/gvsoc/tree/soft_hier_release) | [GVSoC](https://github.com/gvsoc/gvsoc/tree/soft_hier_release) | [![CI • SoftHier](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-softhier.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-softhier.yml) +| **Chimera** | [Repo](https://github.com/pulp-platform/chimera) | [GVSoC](https://github.com/gvsoc/gvsoc) | [![CI • Chimera](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-chimera.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-platform-chimera.yml) ## Publications diff --git a/TargetLibraries/CMSIS/CMakeLists.txt b/TargetLibraries/CMSIS/CMakeLists.txt index 2b6b75d569..1cd382d8ef 100644 --- a/TargetLibraries/CMSIS/CMakeLists.txt +++ b/TargetLibraries/CMSIS/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + file(GLOB_RECURSE SOURCES "src/**" ) diff --git a/TargetLibraries/Chimera/CMakeLists.txt b/TargetLibraries/Chimera/CMakeLists.txt index f3c437c7fd..ba37adb955 100644 --- a/TargetLibraries/Chimera/CMakeLists.txt +++ b/TargetLibraries/Chimera/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + file(GLOB_RECURSE SOURCES "src/**" ) diff --git a/TargetLibraries/Generic/CMakeLists.txt b/TargetLibraries/Generic/CMakeLists.txt index 55bcde77bc..8cdb36f2cf 100644 --- a/TargetLibraries/Generic/CMakeLists.txt +++ b/TargetLibraries/Generic/CMakeLists.txt @@ -1,10 +1,14 @@ -file(GLOB_RECURSE SOURCES +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +file(GLOB_RECURSE SOURCES "src/**" ) add_deeploy_library(deeploybasic STATIC ${SOURCES}) -target_include_directories(deeploybasic +target_include_directories(deeploybasic PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/TargetLibraries/Generic/inc/kernel/Hardswish.h b/TargetLibraries/Generic/inc/kernel/Hardswish.h index 967d2b676a..8e2e06f923 100644 --- a/TargetLibraries/Generic/inc/kernel/Hardswish.h +++ b/TargetLibraries/Generic/inc/kernel/Hardswish.h @@ -24,6 +24,9 @@ # limitations under the License. */ +#ifndef __DEEPLOY_BASIC_MATH_HARDSWISH_KERNEL_HEADER_ +#define __DEEPLOY_BASIC_MATH_HARDSWISH_KERNEL_HEADER_ + #include "DeeployBasicMath.h" /******************************************************************************/ @@ -32,4 +35,6 @@ void iHardswish_s8_s32(int8_t *input, int32_t *output, int32_t size, int32_t one_over_six, int32_t three, int32_t six, - int32_t input_offset); \ No newline at end of file + int32_t input_offset); + +#endif // __DEEPLOY_BASIC_MATH_HARDSWISH_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Generic/inc/kernel/RQHardswish.h b/TargetLibraries/Generic/inc/kernel/RQHardswish.h index 6e2ea7eb79..b66c03d789 100644 --- a/TargetLibraries/Generic/inc/kernel/RQHardswish.h +++ b/TargetLibraries/Generic/inc/kernel/RQHardswish.h @@ -24,6 +24,9 @@ # limitations under the License. */ +#ifndef __DEEPLOY_BASIC_MATH_RQIHARDSWISH_KERNEL_HEADER_ +#define __DEEPLOY_BASIC_MATH_RQIHARDSWISH_KERNEL_HEADER_ + #include "DeeployBasicMath.h" /******************************************************************************/ @@ -34,3 +37,5 @@ void RQiHardswish_s8_s8(int8_t *input, int8_t *output, int32_t size, int32_t one_over_six, int32_t three, int32_t six, int32_t input_offset, int32_t output_offset, int32_t mul, int32_t add, int32_t shift); + +#endif // __DEEPLOY_BASIC_MATH_RQIHARDSWISH_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Relu.h b/TargetLibraries/Generic/inc/kernel/Relu.h index c0da5823c9..535ee4d4d0 100644 --- a/TargetLibraries/Generic/inc/kernel/Relu.h +++ b/TargetLibraries/Generic/inc/kernel/Relu.h @@ -28,6 +28,11 @@ * limitations under the License. */ +#ifndef __DEEPLOY_BASIC_MATH_RELU_KERNEL_HEADER_ +#define __DEEPLOY_BASIC_MATH_RELU_KERNEL_HEADER_ + #include "DeeployBasicMath.h" -void Relu_fp32_fp32(float32_t *input, float32_t *output, int32_t size); \ No newline at end of file +void Relu_fp32_fp32(float32_t *input, float32_t *output, int32_t size); + +#endif // __DEEPLOY_BASIC_MATH_RELU_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/MemPool/CMakeLists.txt b/TargetLibraries/MemPool/CMakeLists.txt index d22180cd52..351b112029 100644 --- a/TargetLibraries/MemPool/CMakeLists.txt +++ b/TargetLibraries/MemPool/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + file(GLOB_RECURSE SOURCES "src/**" ) diff --git a/TargetLibraries/MemPool/cmake/mempool-runtime.cmake b/TargetLibraries/MemPool/cmake/mempool-runtime.cmake index 96cebfd241..aa32e20d27 100644 --- a/TargetLibraries/MemPool/cmake/mempool-runtime.cmake +++ b/TargetLibraries/MemPool/cmake/mempool-runtime.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(MEMPOOL_HOME $ENV{MEMPOOL_HOME}) set(MEMPOOL_RUNTIME_HOME ${MEMPOOL_HOME}/software/runtime) diff --git a/TargetLibraries/PULPOpen/CMakeLists.txt b/TargetLibraries/PULPOpen/CMakeLists.txt index bf67dfca01..d0c24858ca 100644 --- a/TargetLibraries/PULPOpen/CMakeLists.txt +++ b/TargetLibraries/PULPOpen/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + file(GLOB_RECURSE SOURCES "src/**" ) diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake index 8c7109d9c4..0bafa56fbf 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(PULP_SDK_HOME $ENV{PULP_SDK_HOME}) set(PULP_SDK_BASE_C_SOURCE diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake index 3027ddb94e..f7c84d9bc4 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + include(cmake/pulp-sdk-base.cmake) set(PULP_SDK_HOME $ENV{PULP_SDK_HOME}) diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake index c11544dd22..e974cfd1e1 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + include(cmake/pulp-sdk-base.cmake) set(PULP_SDK_HOME $ENV{PULP_SDK_HOME}) diff --git a/TargetLibraries/PULPOpen/inc/kernel/Conv.h b/TargetLibraries/PULPOpen/inc/kernel/Conv.h index e63b7e939f..b573df2d7b 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Conv.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Conv.h @@ -26,6 +26,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_CONV_KERNEL_HEADER_ +#define __DEEPLOY_MATH_CONV_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_Conv2d_fp32_fp32_fp32_HWC(const float32_t *__restrict__ pSrcA, @@ -42,4 +45,6 @@ void PULP_Conv2d_Im2Col_fp32_fp32_fp32_HWC( const float32_t *__restrict__ pSrcB, uint32_t F_total, uint32_t P, uint32_t Q, uint32_t SP, uint32_t SQ, float32_t *__restrict__ pDstC, uint32_t pad_top, uint32_t pad_bottom, uint32_t pad_left, - uint32_t pad_right, float32_t *__restrict__ pContextBuffer); \ No newline at end of file + uint32_t pad_right, float32_t *__restrict__ pContextBuffer); + +#endif // __DEEPLOY_MATH_CONV_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/GELU.h b/TargetLibraries/PULPOpen/inc/kernel/GELU.h index a7cc00f71b..c2a311fdec 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/GELU.h +++ b/TargetLibraries/PULPOpen/inc/kernel/GELU.h @@ -26,10 +26,15 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_GELU_KERNEL_HEADER_ +#define __DEEPLOY_MATH_GELU_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_GELU_fp32_fp32(float32_t *data_in, float32_t *data_out, int32_t dataSize); void PULP_GELU_fp32_fp32_sigmoid(float32_t *data_in, float32_t *data_out, - int32_t dataSize); \ No newline at end of file + int32_t dataSize); + +#endif // __DEEPLOY_MATH_GELU_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h b/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h index 9a63066bd7..78e09e9223 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h @@ -25,9 +25,14 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_LAYERNORM_KERNEL_HEADER_ +#define __DEEPLOY_MATH_LAYERNORM_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_Layernorm_fp32_fp32(float32_t *data_in, float32_t *data_out, float32_t *scale, float32_t *bias, float32_t epsilon, uint32_t size, - uint32_t lastDimLength); \ No newline at end of file + uint32_t lastDimLength); + +#endif // __DEEPLOY_MATH_LAYERNORM_KERNEL_HEADER__ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/Matmul.h b/TargetLibraries/PULPOpen/inc/kernel/Matmul.h index 43a0f3b8a3..c48460b420 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Matmul.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Matmul.h @@ -27,9 +27,14 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ +#define __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_MatMul_fp32_fp32_fp32_unroll1x7(const float32_t *__restrict__ pSrcA, const float32_t *__restrict__ pSrcB, float32_t *__restrict__ pDstY, - uint32_t M, uint32_t N, uint32_t O); \ No newline at end of file + uint32_t M, uint32_t N, uint32_t O); + +#endif // __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h b/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h index d7901ba117..ca5a604286 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h +++ b/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h @@ -25,6 +25,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_MAXPOOL_KERNEL_HEADER_ +#define __DEEPLOY_MATH_MAXPOOL_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_MaxPool2d_fp32_fp32_HWC(const float32_t *__restrict__ pSrcA, @@ -32,4 +35,6 @@ void PULP_MaxPool2d_fp32_fp32_HWC(const float32_t *__restrict__ pSrcA, uint32_t Q, uint32_t P, uint32_t SQ, uint32_t SP, float32_t *__restrict__ pDstC, uint32_t pad_top, uint32_t pad_bottom, - uint32_t pad_left, uint32_t pad_right); \ No newline at end of file + uint32_t pad_left, uint32_t pad_right); + +#endif // __DEEPLOY_MATH_MAXPOOL_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h b/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h index bd528491df..3c08cb7a91 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h +++ b/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h @@ -25,8 +25,13 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_RQIHARDSWISH_KERNEL_HEADER_ +#define __DEEPLOY_MATH_RQIHARDSWISH_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void RQiHardswish_s8_s8_plp(int8_t *input, int8_t *output, int32_t size, int32_t one_over_six, int32_t three, int32_t six, int32_t mul, int32_t add, int32_t shift); + +#endif // __DEEPLOY_MATH_RQIHARDSWISH_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Relu.h b/TargetLibraries/PULPOpen/inc/kernel/Relu.h index 27dc2d8580..4b1246c750 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Relu.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Relu.h @@ -26,6 +26,11 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_RELU_KERNEL_HEADER_ +#define __DEEPLOY_MATH_RELU_KERNEL_HEADER_ + #include "DeeployPULPMath.h" -void PULP_Relu_fp32_fp32(float32_t *input, float32_t *output, uint32_t size); \ No newline at end of file +void PULP_Relu_fp32_fp32(float32_t *input, float32_t *output, uint32_t size); + +#endif // __DEEPLOY_MATH_RELU_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h b/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h index 54c38620a2..70e12accca 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h +++ b/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h @@ -28,6 +28,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_REQUANTSHIFT_KERNEL_HEADER_ +#define __DEEPLOY_MATH_REQUANTSHIFT_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void RequantShift_u8_s8_NHWC(uint8_t *data_in, int32_t size, int32_t *mul, @@ -137,3 +140,5 @@ void RequantShift_s32_u8_NCHW(int32_t *data_in, int32_t size, int32_t *mul, int32_t HW, int32_t input_offset, int32_t output_offset, uint8_t output_min, uint8_t output_max, bool rounding); + +#endif // __DEEPLOY_MATH_REQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Softmax.h b/TargetLibraries/PULPOpen/inc/kernel/Softmax.h index 9e000664c0..9bc3570738 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Softmax.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Softmax.h @@ -25,6 +25,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ +#define __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULPSoftmax_u8_u8(uint8_t *data_in, uint8_t *data_out, @@ -36,4 +39,6 @@ void PULPSoftmax_i8_u8(int8_t *data_in, uint8_t *data_out, uint32_t lastDimLength, int32_t coeffB, int32_t coeffC, int32_t log2); void PULP_Softmax_fp32_fp32(float32_t *input, float32_t *output, uint32_t size, - uint32_t last_dim_length); \ No newline at end of file + uint32_t last_dim_length); + +#endif // __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h b/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h index 0cbd5c28fe..963f2dfb1c 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h +++ b/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h @@ -24,6 +24,9 @@ # limitations under the License. */ +#ifndef __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ +#define __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void UniformRequantShift_s8_s8(int8_t *data_in, int32_t size, int32_t mul, @@ -48,4 +51,6 @@ void UniformRequantShift_s32_s8(int32_t *data_in, int32_t size, int32_t mul, int32_t add, int8_t *data_out, int32_t log2D, int32_t HW, int32_t input_offset, int32_t output_offset, int8_t output_min, - int8_t output_max, bool rounding); \ No newline at end of file + int8_t output_max, bool rounding); + +#endif // __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/gemm.h b/TargetLibraries/PULPOpen/inc/kernel/gemm.h index 95cf0e4800..950182dee1 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/gemm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/gemm.h @@ -26,6 +26,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ +#define __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void PULP_Gemm_fp32_fp32_fp32_fp32(const float32_t *__restrict__ pSrcA, @@ -33,4 +36,6 @@ void PULP_Gemm_fp32_fp32_fp32_fp32(const float32_t *__restrict__ pSrcA, const float32_t *__restrict__ pDstC, float32_t *__restrict__ pDstY, uint32_t M, uint32_t N, uint32_t O, uint32_t transA, - uint32_t transB); \ No newline at end of file + uint32_t transB); + +#endif // __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/gemv.h b/TargetLibraries/PULPOpen/inc/kernel/gemv.h index 214f8300ad..a4a67bc4df 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/gemv.h +++ b/TargetLibraries/PULPOpen/inc/kernel/gemv.h @@ -25,6 +25,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_GEMV_KERNEL_HEADER_ +#define __DEEPLOY_MATH_GEMV_KERNEL_HEADER_ + #include "stdint.h" void gemv_s8_s8_plp(int8_t *pIn, int8_t *pBias, int8_t *pOut, int8_t *pWeight, @@ -32,3 +35,5 @@ void gemv_s8_s8_plp(int8_t *pIn, int8_t *pBias, int8_t *pOut, int8_t *pWeight, uint16_t out_shift, uint16_t dim_vec, uint16_t num_o_neurons, uint8_t flag_relu, uint8_t flag_batch_norm); + +#endif // __DEEPLOY_MATH_GEMV_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h b/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h index fa1c5e4083..766f1daf44 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h @@ -25,7 +25,12 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_IRMSNORM_KERNEL_HEADER_ +#define __DEEPLOY_MATH_IRMSNORM_KERNEL_HEADER_ + #include "DeeployPULPMath.h" void iRMSnorm_s8_s8_plp(int8_t *data_in, int8_t *data_out, int32_t *weight, int32_t size, int32_t lastDimLength, int32_t log2D); + +#endif // __DEEPLOY_MATH_IRMSNORM_KERNEL_HEADER__ diff --git a/TargetLibraries/PULPOpen/inc/mchan_siracusa.h b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h index 2d44d7b29e..3c5e8f7324 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_siracusa.h +++ b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h @@ -1,3 +1,29 @@ +/* ---------------------------------------------------------------------- +# +# File: mchan_siracusa.h +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Luka Macan, luka.macan@unibo.it, University of Bologna +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + // Default mchan base address #ifndef MCHAN_BASE_ADDR #define MCHAN_BASE_ADDR (ARCHI_MCHAN_DEMUX_ADDR) // CLUSTER_MCHAN_ADDR diff --git a/TargetLibraries/PULPOpen/inc/pulp_core.h b/TargetLibraries/PULPOpen/inc/pulp_core.h index 809a16e299..1970fd7f1d 100644 --- a/TargetLibraries/PULPOpen/inc/pulp_core.h +++ b/TargetLibraries/PULPOpen/inc/pulp_core.h @@ -1,3 +1,33 @@ +/* ---------------------------------------------------------------------- +# +# File: pulp_core.h +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Run Wang, runwang@iis.ee.ethz.ch, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ +#ifndef __DEEPLOY_MATH_PULPCORE_HEADER_ +#define __DEEPLOY_MATH_PULPCORE_HEADER_ + #define BEGIN_SINGLE_CORE if (pi_core_id() == 0) { #define END_SINGLE_CORE } -#define SINGLE_CORE if (pi_core_id() == 0) \ No newline at end of file +#define SINGLE_CORE if (pi_core_id() == 0) + +#endif //__DEEPLOY_MATH_PULPCORE_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/CMakeLists.txt b/TargetLibraries/Snitch/CMakeLists.txt index 78a214fea9..859e8798c5 100644 --- a/TargetLibraries/Snitch/CMakeLists.txt +++ b/TargetLibraries/Snitch/CMakeLists.txt @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + file(GLOB_RECURSE SOURCES "src/**" ) diff --git a/TargetLibraries/Snitch/cmake/snitch-runtime-precompiled.cmake b/TargetLibraries/Snitch/cmake/snitch-runtime-precompiled.cmake index a9947dc0ab..85a509a83c 100644 --- a/TargetLibraries/Snitch/cmake/snitch-runtime-precompiled.cmake +++ b/TargetLibraries/Snitch/cmake/snitch-runtime-precompiled.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(SNITCH_RUNTIME_BASE_INCLUDE ${SNITCH_RUNTIME_HOME}/src ${SNITCH_RUNTIME_HOME}/api diff --git a/TargetLibraries/Snitch/inc/dmaStruct.h b/TargetLibraries/Snitch/inc/dmaStruct.h index bf360747e3..e7cbdacbad 100644 --- a/TargetLibraries/Snitch/inc/dmaStruct.h +++ b/TargetLibraries/Snitch/inc/dmaStruct.h @@ -24,6 +24,9 @@ # limitations under the License. */ +#ifndef __DEEPLOY_MATH_DMASTRUCT_HEADER_ +#define __DEEPLOY_MATH_DMASTRUCT_HEADER_ + #include "snrt.h" typedef struct { @@ -34,4 +37,6 @@ typedef struct { size_t src_stride; size_t repeat; snrt_dma_txid_t tid; -} DMA_copy; \ No newline at end of file +} DMA_copy; + +#endif // __DEEPLOY_MATH_DMASTRUCT_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h b/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h index 8c3e3afa12..8d01d35c15 100644 --- a/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h +++ b/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h @@ -1,5 +1,31 @@ -#ifndef __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ -#define __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ +/* ---------------------------------------------------------------------- +# +# File: Gemm_fp32.h +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Taha El Bayed, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + +#ifndef __DEEPLOY_MATH_GEMMFP32_KERNEL_HEADER_ +#define __DEEPLOY_MATH_GEMMFP32_KERNEL_HEADER_ #include "DeeploySnitchMath.h" @@ -48,4 +74,4 @@ void gemm_fp32_opt(uint32_t M, uint32_t N, uint32_t K, float32_t *A, uint32_t ldC, float32_t *Y, uint32_t BETA, uint32_t setup_SSR); -#endif //__DEEPLOY_MATH_GEMM_KERNEL_HEADER_ \ No newline at end of file +#endif //__DEEPLOY_MATH_GEMMFP32_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/inc/kernel/Softmax.h b/TargetLibraries/Snitch/inc/kernel/Softmax.h index fc0bf272f3..32bb658846 100644 --- a/TargetLibraries/Snitch/inc/kernel/Softmax.h +++ b/TargetLibraries/Snitch/inc/kernel/Softmax.h @@ -1,5 +1,36 @@ +/* ---------------------------------------------------------------------- +# +# File: Softmax.h +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Taha El Bayed, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + +#ifndef __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ +#define __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ + #include "DeeploySnitchMath.h" void softmax_fp32(float *input, float *output, int32_t ldI, int32_t batch_offset, int32_t batch_size, int32_t seq_len, - int32_t input_samples); \ No newline at end of file + int32_t input_samples); + +#endif // #define __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h b/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h index 79887d2322..0035301985 100644 --- a/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h +++ b/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h @@ -27,6 +27,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ +#define __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ + #include "DeeploySnitchMath.h" void UniformRequantShift_s8_s8(int8_t *data_in, int32_t size, int32_t mul, @@ -51,4 +54,6 @@ void UniformRequantShift_s32_s8(int32_t *data_in, int32_t size, int32_t mul, int32_t add, int8_t *data_out, int32_t log2D, int32_t HW, int32_t input_offset, int32_t output_offset, int8_t output_min, - int8_t output_max, bool rounding); \ No newline at end of file + int8_t output_max, bool rounding); + +#endif // __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/inc/kernel/iNoNorm.h b/TargetLibraries/Snitch/inc/kernel/iNoNorm.h index 56b58e0959..91b9e8b628 100644 --- a/TargetLibraries/Snitch/inc/kernel/iNoNorm.h +++ b/TargetLibraries/Snitch/inc/kernel/iNoNorm.h @@ -24,8 +24,13 @@ # limitations under the License. */ +#ifndef __DEEPLOY_MATH_INONORM_KERNEL_HEADER_ +#define __DEEPLOY_MATH_INONORM_KERNEL_HEADER_ + #include "DeeploySnitchMath.h" void SnitchiNoNorm_s8_s8(int8_t *data_in, int8_t *data_out, int8_t *weights, int32_t *bias, uint32_t size, int32_t mul, int32_t log2D); + +#endif // __DEEPLOY_MATH_INONORM_KERNEL_HEADER_ \ No newline at end of file diff --git a/TargetLibraries/Snitch/inc/kernel/iSoftmax.h b/TargetLibraries/Snitch/inc/kernel/iSoftmax.h index a59c54e9be..91ab95d502 100644 --- a/TargetLibraries/Snitch/inc/kernel/iSoftmax.h +++ b/TargetLibraries/Snitch/inc/kernel/iSoftmax.h @@ -27,6 +27,9 @@ * limitations under the License. */ +#ifndef __DEEPLOY_MATH_ISOFTMAX_KERNEL_HEADER_ +#define __DEEPLOY_MATH_ISOFTMAX_KERNEL_HEADER_ + #include "DeeploySnitchMath.h" void SnitchSoftmax_u8_u8(uint8_t *data_in, uint8_t *data_out, @@ -37,3 +40,5 @@ void StnichSoftmax_i8_u8(int8_t *data_in, uint8_t *data_out, uint32_t *lastDimBuffer, uint32_t size, uint32_t lastDimLength, int32_t coeffB, int32_t coeffC, int32_t log2); + +#endif // __DEEPLOY_MATH_ISOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/src/Gemm_fp32.c b/TargetLibraries/Snitch/src/Gemm_fp32.c index b9ff58850e..13dce6f9a8 100644 --- a/TargetLibraries/Snitch/src/Gemm_fp32.c +++ b/TargetLibraries/Snitch/src/Gemm_fp32.c @@ -1,3 +1,29 @@ +/* ---------------------------------------------------------------------- +# +# File: Gemm_fp32.c +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Taha El Bayed, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + #include "DeeploySnitchMath.h" #include "Gemm.h" diff --git a/TargetLibraries/Snitch/src/Gemm_s8.c b/TargetLibraries/Snitch/src/Gemm_s8.c index eefd407394..85c9312664 100644 --- a/TargetLibraries/Snitch/src/Gemm_s8.c +++ b/TargetLibraries/Snitch/src/Gemm_s8.c @@ -1,3 +1,29 @@ +/* ---------------------------------------------------------------------- +# +# File: Gemm_s8.c +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Taha El Bayed, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + #include "DeeploySnitchMath.h" #include "Gemm.h" diff --git a/TargetLibraries/Snitch/src/Softmax_fp32.c b/TargetLibraries/Snitch/src/Softmax_fp32.c index 45fb960ffb..b5530808c0 100644 --- a/TargetLibraries/Snitch/src/Softmax_fp32.c +++ b/TargetLibraries/Snitch/src/Softmax_fp32.c @@ -1,3 +1,29 @@ +/* ---------------------------------------------------------------------- +# +# File: Softmax_fp32.c +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Taha El Bayed, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +*/ + #include "DeeploySnitchMath.h" void Softmax_fp32(float32_t *input, float32_t *output, int32_t ldI, diff --git a/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c b/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c index f83e3bac88..3349581a52 100644 --- a/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c +++ b/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c @@ -5,6 +5,8 @@ * * Copyright (C) 2018-2020 University of Bologna * + * SPDX-License-Identifier: Apache-2.0 + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/TargetLibraries/SoftHier/CMakeLists.txt b/TargetLibraries/SoftHier/CMakeLists.txt index d7cab9c559..cbe0cb8032 100644 --- a/TargetLibraries/SoftHier/CMakeLists.txt +++ b/TargetLibraries/SoftHier/CMakeLists.txt @@ -1,17 +1,21 @@ -file(GLOB_RECURSE SOURCES +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +file(GLOB_RECURSE SOURCES "src/**" ) include(cmake/softhier-runtime.cmake) add_deeploy_library(deeploysofthier STATIC ${SOURCES}) -target_include_directories(deeploysofthier +target_include_directories(deeploysofthier PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) target_compile_options(deeploysofthier PRIVATE - -DDEEPLOY_SOFTHIER_PLATFORM + -DDEEPLOY_SOFTHIER_PLATFORM -Wno-implicit-function-declaration -Wno-implicit-int-conversion -Wno-sign-conversion diff --git a/TargetLibraries/SoftHier/cmake/softhier-runtime.cmake b/TargetLibraries/SoftHier/cmake/softhier-runtime.cmake index a0ce19e6c4..dd900b3829 100644 --- a/TargetLibraries/SoftHier/cmake/softhier-runtime.cmake +++ b/TargetLibraries/SoftHier/cmake/softhier-runtime.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + # SoftHier runtime should have structure: # runtime/ # ├── include/ @@ -23,7 +27,7 @@ set_source_files_properties( -add_library(softhier-sdk OBJECT +add_library(softhier-sdk OBJECT ${SOFTHIER_RUNTIME_ASM_SOURCE} ) @@ -32,7 +36,7 @@ target_compile_options(softhier-sdk PRIVATE ) target_include_directories(softhier-sdk SYSTEM PUBLIC ${SOFTHIER_INCLUDES}) -target_compile_options(softhier-sdk PRIVATE +target_compile_options(softhier-sdk PRIVATE -Wno-sign-conversion -Wno-unused-function -Wno-unused-parameter diff --git a/cmake/Util.cmake b/cmake/Util.cmake index 88bc48007b..983c6d9574 100644 --- a/cmake/Util.cmake +++ b/cmake/Util.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + macro(add_deeploy_library name) add_library(${ARGV}) add_custom_command( diff --git a/cmake/chimera/chimera-sdk.cmake b/cmake/chimera/chimera-sdk.cmake index c54b4573dd..468cd1fb90 100644 --- a/cmake/chimera/chimera-sdk.cmake +++ b/cmake/chimera/chimera-sdk.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + add_compile_definitions( DEEPLOY_CHIMERA_PLATFORM ) diff --git a/cmake/chimera/toolchain_llvm.cmake b/cmake/chimera/toolchain_llvm.cmake index cbb6d84bfd..b82cc971d4 100644 --- a/cmake/chimera/toolchain_llvm.cmake +++ b/cmake/chimera/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) @@ -13,7 +17,7 @@ set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}/ld.lld) set(CMAKE_EXECUTABLE_SUFFIX ".elf") # Enable WHOLE_ARCHIVE feature -set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "-Wl,--whole-archive -Wl,--no-whole-archive" ) set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED True) diff --git a/cmake/cmsis/cmsis.cmake b/cmake/cmsis/cmsis.cmake index f10892c87b..e6427e736c 100644 --- a/cmake/cmsis/cmsis.cmake +++ b/cmake/cmsis/cmsis.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + add_compile_definitions( DEEPLOY_CMSIS_PLATFORM ) diff --git a/cmake/cmsis/qemu.cmake b/cmake/cmsis/qemu.cmake index d8b8e04512..d9a2bec5f9 100644 --- a/cmake/cmsis/qemu.cmake +++ b/cmake/cmsis/qemu.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TARGET_CPU "cortex-m4" CACHE STRING "Target CPU") set(CPU cortex-m4) set(FPU fpv4-sp-d16) diff --git a/cmake/cmsis/toolchain_gcc.cmake b/cmake/cmsis/toolchain_gcc.cmake index c99245b93e..4c4aa39058 100644 --- a/cmake/cmsis/toolchain_gcc.cmake +++ b/cmake/cmsis/toolchain_gcc.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX arm-none-eabi) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/cmsis/toolchain_llvm.cmake b/cmake/cmsis/toolchain_llvm.cmake index 8a329b1aaa..76454e4e9d 100644 --- a/cmake/cmsis/toolchain_llvm.cmake +++ b/cmake/cmsis/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/common.cmake b/cmake/common.cmake index c090edf525..eff1505f09 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) diff --git a/cmake/generic/generic.cmake b/cmake/generic/generic.cmake index 63c17b1024..eb58af3b2e 100644 --- a/cmake/generic/generic.cmake +++ b/cmake/generic/generic.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + add_compile_definitions( DEEPLOY_GENERIC_PLATFORM ) diff --git a/cmake/generic/toolchain_llvm.cmake b/cmake/generic/toolchain_llvm.cmake index fbe119d717..88888d2acd 100644 --- a/cmake/generic/toolchain_llvm.cmake +++ b/cmake/generic/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/mempool/mempool.cmake b/cmake/mempool/mempool.cmake index 9ba4070c58..2a71dcec09 100644 --- a/cmake/mempool/mempool.cmake +++ b/cmake/mempool/mempool.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + ############################# ## Address configuration ## ############################# diff --git a/cmake/mempool/mempool_ita.cmake b/cmake/mempool/mempool_ita.cmake index bc3631c6d2..5fc050ec21 100644 --- a/cmake/mempool/mempool_ita.cmake +++ b/cmake/mempool/mempool_ita.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + ############################# ## Address configuration ## ############################# diff --git a/cmake/mempool/minpool.cmake b/cmake/mempool/minpool.cmake index 3c688504ae..8d93246fc8 100644 --- a/cmake/mempool/minpool.cmake +++ b/cmake/mempool/minpool.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + ############################# ## Address configuration ## ############################# diff --git a/cmake/mempool/toolchain_gcc.cmake b/cmake/mempool/toolchain_gcc.cmake index fa0636f72d..a02ea55ce5 100644 --- a/cmake/mempool/toolchain_gcc.cmake +++ b/cmake/mempool/toolchain_gcc.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin/riscv32-unknown-elf) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/mempool/toolchain_llvm.cmake b/cmake/mempool/toolchain_llvm.cmake index fe66233360..d84dbff293 100644 --- a/cmake/mempool/toolchain_llvm.cmake +++ b/cmake/mempool/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/pulp/pulp-open/pulp-open.cmake b/cmake/pulp/pulp-open/pulp-open.cmake index c8d7454f11..bc60586b15 100644 --- a/cmake/pulp/pulp-open/pulp-open.cmake +++ b/cmake/pulp/pulp-open/pulp-open.cmake @@ -1,2 +1,6 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(PULPNNVERSION XPULPV2) set(PULPNNBITWIDTH 32) diff --git a/cmake/pulp/pulp.cmake b/cmake/pulp/pulp.cmake index 242e798e29..56fb3dbbf3 100644 --- a/cmake/pulp/pulp.cmake +++ b/cmake/pulp/pulp.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + add_compile_definitions( DEEPLOY_PULP_PLATFORM ) diff --git a/cmake/pulp/siracusa/siracusa.cmake b/cmake/pulp/siracusa/siracusa.cmake index c8d7454f11..bc60586b15 100644 --- a/cmake/pulp/siracusa/siracusa.cmake +++ b/cmake/pulp/siracusa/siracusa.cmake @@ -1,2 +1,6 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(PULPNNVERSION XPULPV2) set(PULPNNBITWIDTH 32) diff --git a/cmake/pulp/toolchain_gcc.cmake b/cmake/pulp/toolchain_gcc.cmake index a5681a319a..4df6f0639f 100644 --- a/cmake/pulp/toolchain_gcc.cmake +++ b/cmake/pulp/toolchain_gcc.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin/riscv32-unknown-elf) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/pulp/toolchain_llvm.cmake b/cmake/pulp/toolchain_llvm.cmake index c0c6952e52..4e995c3b55 100644 --- a/cmake/pulp/toolchain_llvm.cmake +++ b/cmake/pulp/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/simulation.cmake b/cmake/simulation.cmake index 96bb45af9e..b6a99cd408 100644 --- a/cmake/simulation.cmake +++ b/cmake/simulation.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + ######################### ## Simulation Config ## ######################### diff --git a/cmake/snitch/snitch.cmake b/cmake/snitch/snitch.cmake index 9a12366fbd..47b1a046b8 100644 --- a/cmake/snitch/snitch.cmake +++ b/cmake/snitch/snitch.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + if(NOT DEFINED ENV{SNITCH_HOME}) message(FATAL_ERROR "Environment variable SNITCH_HOME not set.") endif() diff --git a/cmake/snitch/snitch_cluster/snitch_cluster.cmake b/cmake/snitch/snitch_cluster/snitch_cluster.cmake index 38b0b07b73..765d4deb2d 100644 --- a/cmake/snitch/snitch_cluster/snitch_cluster.cmake +++ b/cmake/snitch/snitch_cluster/snitch_cluster.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(SNITCH_CLUSTER_HOME ${SNITCH_HOME}/target/snitch_cluster) set(BANSHEE_CONFIG ${SNITCH_CLUSTER_HOME}/src/banshee.yaml CACHE INTERNAL "source_list") \ No newline at end of file diff --git a/cmake/snitch/toolchain_llvm.cmake b/cmake/snitch/toolchain_llvm.cmake index b6c6f23d22..51c63c554b 100644 --- a/cmake/snitch/toolchain_llvm.cmake +++ b/cmake/snitch/toolchain_llvm.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) set(CMAKE_SYSTEM_NAME Generic) diff --git a/cmake/softhier/softhier_gvsoc.cmake b/cmake/softhier/softhier_gvsoc.cmake index 49dc6ec121..ca21b63d97 100644 --- a/cmake/softhier/softhier_gvsoc.cmake +++ b/cmake/softhier/softhier_gvsoc.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + macro(add_gvsoc_emulation name) set(BINARY_PATH ${CMAKE_BINARY_DIR}/bin/${name}) diff --git a/cmake/softhier/toolchain_gcc.cmake b/cmake/softhier/toolchain_gcc.cmake index ef1cee12b0..1bea73b268 100644 --- a/cmake/softhier/toolchain_gcc.cmake +++ b/cmake/softhier/toolchain_gcc.cmake @@ -1,3 +1,7 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + add_compile_definitions( DEEPLOY_SOFTHIER_PLATFORM ) @@ -20,15 +24,15 @@ set(ISA rv32imafdv_zfh) set(CMAKE_EXECUTABLE_SUFFIX ".elf") add_compile_options( - -mabi=ilp32d + -mabi=ilp32d -mcmodel=medlow -march=${ISA} - -g - -O3 + -g + -O3 -ffast-math - -fno-builtin - -fno-tree-vectorize - -fno-common + -fno-builtin + -fno-tree-vectorize + -fno-common -ffunction-sections -fno-strict-aliasing ) @@ -36,7 +40,7 @@ add_compile_options( add_link_options( -march=${ISA} -nostartfiles - -Wl,--gc-sections + -Wl,--gc-sections ) link_libraries( diff --git a/requirements-dev.txt b/requirements-dev.txt index ed846e9b09..a90062f113 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -15,6 +15,7 @@ pyserial yapf==0.33.0 isort==5.12.0 autoflake==2.3.0 +yamllint==1.37.1 clang-format # Documentation diff --git a/scripts/gen_changelog.py b/scripts/gen_changelog.py index 8e981071ef..d54cd42355 100644 --- a/scripts/gen_changelog.py +++ b/scripts/gen_changelog.py @@ -1,3 +1,29 @@ +# ---------------------------------------------------------------------- +# +# File: MchanDma.py +# +# Last edited: 11.09.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Philip Wiese, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import re import subprocess from collections import defaultdict From 59ac79ecf56e2f142c76ce36bfffa6188ea0d23f Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Tue, 16 Sep 2025 10:07:47 +0200 Subject: [PATCH 07/28] Fix PULP GEMM `batch` serialization (#109) PULPOpen: Fix serialization of the batch variable in MatMul and GEMM tile constraints --- .../workflows/ci-platform-siracusa-tiled.yml | 4 +- CHANGELOG.md | 2 + .../TileConstraints/GEMMTileConstraint.py | 193 ++++++------------ .../TileConstraints/MatMulTileConstraint.py | 71 +++---- Deeploy/Targets/PULPOpen/Tiler.py | 7 +- DeeployTest/Tests/testMatMulBatch/inputs.npz | Bin 0 -> 1538 bytes .../Tests/testMatMulBatch/network.onnx | Bin 0 -> 188 bytes DeeployTest/Tests/testMatMulBatch/outputs.npz | Bin 0 -> 522 bytes DeeployTest/Tests/testRQGEMMwBatch/inputs.npz | Bin 0 -> 384 bytes .../Tests/testRQGEMMwBatch/network.onnx | Bin 0 -> 805 bytes .../Tests/testRQGEMMwBatch/outputs.npz | Bin 0 -> 330 bytes 11 files changed, 91 insertions(+), 186 deletions(-) create mode 100644 DeeployTest/Tests/testMatMulBatch/inputs.npz create mode 100644 DeeployTest/Tests/testMatMulBatch/network.onnx create mode 100644 DeeployTest/Tests/testMatMulBatch/outputs.npz create mode 100644 DeeployTest/Tests/testRQGEMMwBatch/inputs.npz create mode 100644 DeeployTest/Tests/testRQGEMMwBatch/network.onnx create mode 100644 DeeployTest/Tests/testRQGEMMwBatch/outputs.npz diff --git a/.github/workflows/ci-platform-siracusa-tiled.yml b/.github/workflows/ci-platform-siracusa-tiled.yml index 26cef57ffd..0791eab317 100644 --- a/.github/workflows/ci-platform-siracusa-tiled.yml +++ b/.github/workflows/ci-platform-siracusa-tiled.yml @@ -55,7 +55,9 @@ jobs: {"name":"testFloatSoftmax","L1":[4000]}, {"name":"testFloatTranspose","L1":[2000]}, {"name":"testFloatMul","L1":[2000]}, - {"name":"largeFloatAdd","L1":[220000]} + {"name":"largeFloatAdd","L1":[220000]}, + {"name":"testRQGEMMwBatch","L1":[20000]}, + {"name":"testMatMulBatch","L1":[20000]} ] num-cores: 8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a86155168..6d0e71bbcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Fix PULP GEMM `batch` serialization [#109](https://github.com/pulp-platform/Deeploy/pull/109) - Split CI Workflows by Platform and Task, Improve Formatting and Linting Reliability [#108](https://github.com/pulp-platform/Deeploy/pull/108) - Refactor tiling code generation [#105](https://github.com/pulp-platform/Deeploy/pull/105) - Change order of typeMatching entries [#68](https://github.com/pulp-platform/Deeploy/pull/68) @@ -61,6 +62,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Prevent node duplication for graphs generated via GraphSurgeon - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. - Fix license CI check and prevent potential issues with `jq` installation +- PULP Gemm `batch` variable serialization ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py index 4206be3390..ea5c7d0cb4 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py @@ -24,6 +24,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import math from typing import Dict, List, Tuple from Deeploy.AbstractDataTypes import PointerClass @@ -135,25 +136,22 @@ def serializeTilingSolution( # Every output is constructed by a pair of inputs. Reconstruct this pair. for cube in outputCubes: + MOffset, OOffset = cube.offset[-2:] + MSize, OSize = cube.dims[-2:] - BSize = 1 - BOffset = 0 - BatchSize = 1 - BatchOffset = 0 - - if len(cube.offset) == 2: - (MOffset, OOffset) = cube.offset - (MSize, OSize) = cube.dims - elif len(cube.offset) == 3: - (BatchOffset, MOffset, OOffset) = cube.offset - (BatchSize, MSize, OSize) = cube.dims + if len(cube.offset) > 2: + BatchSize = math.prod(cube.dims[:-2]) + + if len(cube.offset) > 3: + assert all(off == 0 for off in cube.offset[:-3]), ( + f"Unsupported tiling across leading batch dims: offsets={cube.offset}. " + "Only the last batch dim (besides M/O) may be tiled.") else: - (BatchOffset, BOffset, MOffset, OOffset) = cube.offset - (BatchSize, BSize, MSize, OSize) = cube.dims + BatchSize = 1 replacements["M"].append(MSize) replacements["O"].append(OSize) - replacements["batch"].append(BSize) + replacements["batch"].append(BatchSize) if transA == 0: AMatrixOffsets = (MOffset, NOffset) @@ -162,6 +160,14 @@ def serializeTilingSolution( AMatrixOffsets = (NOffset, MOffset) AMatrixShape = (NSize, MSize) + if len(buffA.shape) > 2: + batchDimCount = len(buffA.shape) - 2 + AMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + AMatrixOffsets + AMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + AMatrixShape + + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + inputACubes.append(ACube) + if transB == 0: BMatrixOffsets = (NOffset, OOffset) BMatrixShape = (NSize, OSize) @@ -169,42 +175,15 @@ def serializeTilingSolution( BMatrixOffsets = (OOffset, NOffset) BMatrixShape = (OSize, NSize) - if len(buffA.shape) == 2: - ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) - elif len(buffA.shape) == 3: - ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) - else: - ACube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + AMatrixOffsets, - ( - BatchSize, - BSize, - ) + AMatrixShape, - ) - - if len(buffB.shape) == 2: - BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) - elif len(buffB.shape) == 3: - BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) - else: - BCube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + BMatrixOffsets, - ( - BatchSize, - BSize, - ) + BMatrixShape, - ) - - RequantCube = HyperRectangle((OOffset,), (OSize,)) + if len(buffB.shape) > 2: + batchDimCount = len(buffB.shape) - 2 + BMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + BMatrixOffsets + BMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + BMatrixShape - inputACubes.append(ACube) + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) inputBCubes.append(BCube) + + RequantCube = HyperRectangle((OOffset,), (OSize,)) inputMulCubes.append(RequantCube) inputAddCubes.append(RequantCube) @@ -231,40 +210,6 @@ def serializeTilingSolution( return VariableReplacementScheme(replacements, replacementTypes), schedule -class MatrixVecTileConstraint(GEMMTileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - tm = GEMMTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - return tm - - @staticmethod - def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - tm = GEMMTileConstraint.addPolicyConstraint(tilerModel, parseDict, ctxt) - - return tm - - -class TallGEMMTileConstraint(GEMMTileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - tm = GEMMTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - return tm - - @staticmethod - def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - tm = GEMMTileConstraint.addPolicyConstraint(tilerModel, parseDict, ctxt) - - return tm - - class FloatGEMMTileConstraint(TileConstraint): @staticmethod @@ -367,25 +312,22 @@ def serializeTilingSolution( # Every output is constructed by a pair of inputs. Reconstruct this pair. for cube in outputCubes: + MOffset, OOffset = cube.offset[-2:] + MSize, OSize = cube.dims[-2:] - BSize = 1 - BOffset = 0 - BatchSize = 1 - BatchOffset = 0 - - if len(cube.offset) == 2: - (MOffset, OOffset) = cube.offset - (MSize, OSize) = cube.dims - elif len(cube.offset) == 3: - (BatchOffset, MOffset, OOffset) = cube.offset - (BatchSize, MSize, OSize) = cube.dims + if len(cube.offset) > 2: + BatchSize = math.prod(cube.dims[:-2]) + + if len(cube.offset) > 3: + assert all(off == 0 for off in cube.offset[:-3]), ( + f"Unsupported tiling across leading batch dims: offsets={cube.offset}. " + "Only the last batch dim (besides M/O) may be tiled.") else: - (BatchOffset, BOffset, MOffset, OOffset) = cube.offset - (BatchSize, BSize, MSize, OSize) = cube.dims + BatchSize = 1 replacements["M"].append(MSize) replacements["O"].append(OSize) - replacements["batch"].append(BSize) + replacements["batch"].append(BatchSize) if transA == 0: AMatrixOffsets = (MOffset, NOffset) @@ -394,6 +336,14 @@ def serializeTilingSolution( AMatrixOffsets = (NOffset, MOffset) AMatrixShape = (NSize, MSize) + if len(buffA.shape) > 2: + batchDimCount = len(buffA.shape) - 2 + AMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + AMatrixOffsets + AMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + AMatrixShape + + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + inputACubes.append(ACube) + if transB == 0: BMatrixOffsets = (NOffset, OOffset) BMatrixShape = (NSize, OSize) @@ -401,50 +351,23 @@ def serializeTilingSolution( BMatrixOffsets = (OOffset, NOffset) BMatrixShape = (OSize, NSize) - if len(buffA.shape) == 2: - ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) - elif len(buffA.shape) == 3: - ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) - else: - ACube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + AMatrixOffsets, - ( - BatchSize, - BSize, - ) + AMatrixShape, - ) - - if len(buffB.shape) == 2: - BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) - elif len(buffB.shape) == 3: - BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) - else: - BCube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + BMatrixOffsets, - ( - BatchSize, - BSize, - ) + BMatrixShape, - ) + if len(buffB.shape) > 2: + batchDimCount = len(buffB.shape) - 2 + BMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + BMatrixOffsets + BMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + BMatrixShape + + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) + inputBCubes.append(BCube) CMatrixOffsets = (MOffset, OOffset) CMatrixShape = (MSize, OSize) - if len(buffC.shape) == 2: - CCube = HyperRectangle(CMatrixOffsets, CMatrixShape) - elif len(buffC.shape) == 3: - CCube = HyperRectangle((BatchOffset,) + CMatrixOffsets, (BatchSize,) + CMatrixShape) - else: - CCube = HyperRectangle((BatchOffset, BOffset) + CMatrixOffsets, (BatchSize, BSize) + CMatrixShape) + if len(buffC.shape) > 2: + batchDimCount = len(buffC.shape) - 2 + CMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + CMatrixOffsets + CMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + CMatrixShape - inputACubes.append(ACube) - inputBCubes.append(BCube) + CCube = HyperRectangle(CMatrixOffsets, CMatrixShape) inputAddCubes.append(CCube) inputLoadSchedule = [] diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py index cae635b5fc..1c04adb986 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py @@ -24,6 +24,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import math from typing import Dict, List, Tuple from Deeploy.AbstractDataTypes import PointerClass @@ -125,65 +126,43 @@ def serializeTilingSolution( # Every output is constructed by a pair of inputs. Reconstruct this pair. for cube in outputCubes: + MOffset, OOffset = cube.offset[-2:] + MSize, OSize = cube.dims[-2:] - BSize = 1 - BOffset = 0 - BatchSize = 1 - BatchOffset = 0 - - if len(cube.offset) == 2: - (MOffset, OOffset) = cube.offset - (MSize, OSize) = cube.dims - elif len(cube.offset) == 3: - (BatchOffset, MOffset, OOffset) = cube.offset - (BatchSize, MSize, OSize) = cube.dims + if len(cube.offset) > 2: + BatchSize = math.prod(cube.dims[:-2]) + + if len(cube.offset) > 3: + assert all(off == 0 for off in cube.offset[:-3]), ( + f"Unsupported tiling across leading batch dims: offsets={cube.offset}. " + "Only the last batch dim (besides M/O) may be tiled.") else: - (BatchOffset, BOffset, MOffset, OOffset) = cube.offset - (BatchSize, BSize, MSize, OSize) = cube.dims + BatchSize = 1 replacements["M"].append(MSize) replacements["O"].append(OSize) - replacements["batch"].append(BSize) + replacements["batch"].append(BatchSize) AMatrixOffsets = (MOffset, NOffset) AMatrixShape = (MSize, NSize) + if len(buffA.shape) > 2: + batchDimCount = len(buffA.shape) - 2 + AMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + AMatrixOffsets + AMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + AMatrixShape + + ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) + inputACubes.append(ACube) + BMatrixOffsets = (NOffset, OOffset) BMatrixShape = (NSize, OSize) - if len(buffA.shape) == 2: - ACube = HyperRectangle(AMatrixOffsets, AMatrixShape) - elif len(buffA.shape) == 3: - ACube = HyperRectangle((BatchOffset,) + AMatrixOffsets, (BatchSize,) + AMatrixShape) - else: - ACube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + AMatrixOffsets, - ( - BatchSize, - BSize, - ) + AMatrixShape, - ) - - if len(buffB.shape) == 2: - BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) - elif len(buffB.shape) == 3: - BCube = HyperRectangle((BatchOffset,) + BMatrixOffsets, (BatchSize,) + BMatrixShape) - else: - BCube = HyperRectangle( - ( - BatchOffset, - BOffset, - ) + BMatrixOffsets, - ( - BatchSize, - BSize, - ) + BMatrixShape, - ) + if len(buffB.shape) > 2: + batchDimCount = len(buffB.shape) - 2 + BMatrixOffsets = tuple(cube.offset[:-2][-batchDimCount:]) + BMatrixOffsets + BMatrixShape = tuple(cube.dims[:-2][-batchDimCount:]) + BMatrixShape - inputACubes.append(ACube) + BCube = HyperRectangle(BMatrixOffsets, BMatrixShape) inputBCubes.append(BCube) inputLoadSchedule = [] diff --git a/Deeploy/Targets/PULPOpen/Tiler.py b/Deeploy/Targets/PULPOpen/Tiler.py index ea48ac9b21..62c8090c16 100644 --- a/Deeploy/Targets/PULPOpen/Tiler.py +++ b/Deeploy/Targets/PULPOpen/Tiler.py @@ -50,8 +50,7 @@ from Deeploy.Targets.PULPOpen.TileConstraints.ConvTileConstraint import Conv2DTileConstraint, RQConv2DTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.DWConvTileConstraint import DWConv2DTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.GatherTileConstraint import GatherTileConstraint -from Deeploy.Targets.PULPOpen.TileConstraints.GEMMTileConstraint import FloatGEMMTileConstraint, GEMMTileConstraint, \ - MatrixVecTileConstraint, TallGEMMTileConstraint +from Deeploy.Targets.PULPOpen.TileConstraints.GEMMTileConstraint import FloatGEMMTileConstraint, GEMMTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.iSoftmaxTileConstraint import iSoftmaxTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.LayernormTileConstraint import LayernormTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.MatMulTileConstraint import MatMulTileConstraint @@ -78,10 +77,10 @@ tileConstraint = FloatGEMMTileConstraint()) PULPRQSMatrixVecTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = PULPRQSMatrixVecBindings, - tileConstraint = MatrixVecTileConstraint()) + tileConstraint = GEMMTileConstraint()) PULPRQSTallGEMMTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = PULPRQSTallGEMMBindings, - tileConstraint = TallGEMMTileConstraint()) + tileConstraint = GEMMTileConstraint()) PULPMatMulTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = PULPMatMulBindings, tileConstraint = MatMulTileConstraint()) diff --git a/DeeployTest/Tests/testMatMulBatch/inputs.npz b/DeeployTest/Tests/testMatMulBatch/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..d9098e15d3a3b9b118220279d2e7306a2e5694f5 GIT binary patch literal 1538 zcmcJPy=zlZ7>7?%>!3@9{sGr13PDonP(<<8!KEm7ad2viO;M2cl2-8p;fxsrE*Uds z%-BV|EeIJicD!T9j2(TR+?HCwMe(*jfA9OA_xl{1Z7$td3DtKeG}n(l#Cizgc325- z_VRa!TkZRM`NvvlEX=xk?DzHgi)Y!(T6iBmH+Q-RuX@b~N%P_ETC&{TP>l1bLtgYmdkiSVUlM`xyai=<6QrLz^>N*LhQH9axyh{2kB- z<}NsIBWrhNYm~rV0`SZo6!3hb+QAI=KAd5EoLzgo^(Q|b#X2$I>hZ4r$H%+Q`~8Q< zyBL%u3>YxL4m<>r;TmuWQs4rWU4niC*h@Xa7J+(5If6@ge4(evf%632OY-tupi4D2 zNA@zNARt>`-OEV9sHiYOj^GHK0?(|WuQA#SYURlGYwr_K5^pX2&(QtGa0bk`==+4& z;_A{n*sW)8A+2(GK0U53-8yaL0chakW9xttxdEGh(KmkXsE=+QXS%HE4BFEIU+u7U z-ARdWf}Fzo8K=!Up}-e*CTm(pyS5=H(C4r{n8O{JcMbxWffV#XzL9O#>MKis`rAvy o#TRP|zx*ZsJ@ERwzYL?T+PC^;;NpKlwz+)M<2pY*_|vl5Pr_nn{{R30 literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testMatMulBatch/network.onnx b/DeeployTest/Tests/testMatMulBatch/network.onnx new file mode 100644 index 0000000000000000000000000000000000000000..f8e86371f05ac824d084828bba350826e5a17ae8 GIT binary patch literal 188 zcmdqQ}gp6oG3+@UIQU9E)fn!AptHX4i+G0gwh-cC5Bj(aDbF0DR4n8 Q#-ajb7>g4N7lQyd03FXIbN~PV literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testMatMulBatch/outputs.npz b/DeeployTest/Tests/testMatMulBatch/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..a3ed1f597ae0efda161f6a36e58abbf4e0807785 GIT binary patch literal 522 zcmbVJJxjw-6g{yjQV;~|po?jt#E+mB3W{`So7BN#>7Yml(PC2^q$z1Dh$s&SHwO_M zrJIP0AWk~8CQc%#lY{uNx%dM_5Kr2{$;JD4@8q0&?!AGVPI_8>XoerbqtSaI0q*s} z2eVQxR>~uV;<|*chUz-qtQ-5OxtVlE!WuS|oKae~lu22M*Y2^%8 zpUSS54CWGGj6&=+&eL?aBeQF#_2gK(%a6x~}K`lal&ia00j|1^x1CMp!^$M7!FGPOJ zn_>RF4lz&M)gbS%|AU6=wgcR-KEQv8F~^xOG~D$iP(9`R7xp})4+)5G9kov8zv$f~ zrr2YPT7chz^M-AV^x^OefpgU0vdtAYL~1 F`2&-wdP4vJ literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testRQGEMMwBatch/inputs.npz b/DeeployTest/Tests/testRQGEMMwBatch/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..beb5343bfabfa1a8543225057bc6bd734c418d46 GIT binary patch literal 384 zcmWIWW@Zs#fB;1X`;$(}42(b?5VJCfFjVN}6;v`Z2!I8^ia?S;FxfBEHz1Ocp^Twg zJteg`xk%kgLER?JL|sQgJuSbeq$n{jKEEg>6(sJKm{Xhz6fe$5EJy|NHH>r=fXG5q zN1;}MJirBXf)fM7kwXj&0gem|pMdOTKz0w1UT~0sp$SMA0L2-ASOFvk#ODq%FmM1d zNRJMXe+o#0^cDcwF+e;E$lnLV&wzLd5bttgVE6^3Q-Jg&AUz34uK=380f;9Z3h-uR h5@E&_aG(%^fCfeo4GzWtZ&o%ChY<*kfwVbT3IJTrM`Qp1 literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testRQGEMMwBatch/network.onnx b/DeeployTest/Tests/testRQGEMMwBatch/network.onnx new file mode 100644 index 0000000000000000000000000000000000000000..eaf45f0ff4d99eb2cfd187c00814bd7c490abebb GIT binary patch literal 805 zcmZuuKTq3G5Wfdb`g9GAWu!vgN{v#rLLMw9NDM3uCS4-2w4J&*^Bf!}q8k&c zGW82o%Gi&<2w`FF(79v3K-a40_lyKI!|C1q{+!<3akL%{Kj&$-Kd>upcgyv*|5R|! ztjZ)vglE@f8b)F_m7_e6x!7#-+uZraun>(S=PTo!8z%F$sdvTzW|sim2l%oBFr5Q5 zu5^7#c!Myw2KYgIk#~vzOZkvuKr!n8oYC8%_)YwGih}z^_yy(39N?Vlf;X=KZU|ea zd`eO1Kl(Ff;0Cf&^+Vz5X_p}^D)&wpigt6E9{kDhp$M^%ieu{Um3cr0&#LNfc2)6Sv-UnZ8PiHX4B~^_Y2b1g zPn@Tm(H3_tGb)GODWH8;dz7AQG6()(0QiR zE2Ub4O81s@+w~xJQz=i~{Z!^z+_&&Jh^08pg5kh(nw(iRT;fY*@cs)d7qx&jj@EAP`2=fZlWUHca*pVpPRV literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testRQGEMMwBatch/outputs.npz b/DeeployTest/Tests/testRQGEMMwBatch/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..65781132953b105a613a0478db7158a844f44892 GIT binary patch literal 330 zcmWIWW@Zs#fB;2?-Ung+2Y?(9=3)?G$jQu0O)S#OE2v~-5CDq;CE)aAzfj+RNJfS- zhHCYc)Z*kKbt?sRn=})39R>BY{GyVg#Ju?YqLfsSxLaaQaVk)}I3uwj70A~x(op~+ z6HOh3S_Sd|7X!mTCj@3V40IY0!^B{G7!4AKu_1JTHzSh>GcMnQd

#j362j76IO@ QY# Date: Tue, 16 Sep 2025 13:29:55 +0200 Subject: [PATCH 08/28] Bug fixes, API Cleanup and Reduce Compiler Warning on PULP (#112) - Reshape operator support for PULP (`ReshapeTemplate` in bindings) - Missing class attributes in `Closure.py` - Removed unnecessary includes from the PULP platform header list, such as `DeeployBasicMath.h`, for cleaner code generation - Changed types and added correct casts to fix many compiler warnings in the PULP target library - Fixed multiple typos in variable and method names, such as changing `includeGobalReferences` to `includeGlobalReferences` and `dicardedMappers` to `discardedMappers` - Corrected method usage in `importDeeployState` to call `NetworkContext.importNetworkContext` instead of the incorrect method name - Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` --- CHANGELOG.md | 8 + .../CodeTransformationPasses/Closure.py | 3 +- .../IntrospectiveCodeTransformation.py | 8 +- .../MemoryAllocation.py | 7 +- .../CodeTransformationPasses/PrintInputs.py | 12 +- Deeploy/DeeployTypes.py | 6 +- Deeploy/Targets/PULPOpen/Bindings.py | 24 ++- Deeploy/Targets/PULPOpen/Platform.py | 3 +- .../PULPOpen/Templates/ReshapeTemplate.py | 59 +++++++ Deeploy/Targets/PULPOpen/Tiler.py | 16 +- .../TilingPrototypes.py | 4 +- .../Platforms/PULPOpen/src/deeploytest.c | 161 +++++++++++++----- .../Platforms/Siracusa/src/deeploytest.c | 42 ++--- DeeployTest/testMVP.py | 17 +- DeeployTest/testRunner_tiled_siracusa.py | 3 +- DeeployTest/testUtils/codeGenerate.py | 58 ++++--- README.md | 3 +- TargetLibraries/PULPOpen/CMakeLists.txt | 12 ++ TargetLibraries/PULPOpen/inc/DeeployMath.h | 45 ----- .../PULPOpen/inc/DeeployPULPMath.h | 6 + .../PULPOpen/src/Convolution_fp32.c | 4 +- TargetLibraries/PULPOpen/src/GELU.c | 6 +- TargetLibraries/PULPOpen/src/Gemm.c | 2 +- TargetLibraries/PULPOpen/src/Layernorm.c | 4 +- TargetLibraries/PULPOpen/src/Matmul.c | 4 +- TargetLibraries/PULPOpen/src/MaxPool.c | 2 +- TargetLibraries/PULPOpen/src/RQiHardswish.c | 2 +- TargetLibraries/PULPOpen/src/Relu.c | 2 +- TargetLibraries/PULPOpen/src/Softmax.c | 2 +- .../PULPOpen/src/UniformRequantShift.c | 8 +- TargetLibraries/PULPOpen/src/Util.c | 2 +- TargetLibraries/PULPOpen/src/dory_mem.c | 26 +-- TargetLibraries/PULPOpen/src/gemv.c | 2 +- TargetLibraries/PULPOpen/src/iRMSnorm.c | 2 +- 34 files changed, 355 insertions(+), 210 deletions(-) create mode 100644 Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py delete mode 100644 TargetLibraries/PULPOpen/inc/DeeployMath.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d0e71bbcb..cacea0f199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Bug fixes, API Cleanup and Reduce Compiler Warning on PULP [#112](https://github.com/pulp-platform/Deeploy/pull/112) - Fix PULP GEMM `batch` serialization [#109](https://github.com/pulp-platform/Deeploy/pull/109) - Split CI Workflows by Platform and Task, Improve Formatting and Linting Reliability [#108](https://github.com/pulp-platform/Deeploy/pull/108) - Refactor tiling code generation [#105](https://github.com/pulp-platform/Deeploy/pull/105) @@ -34,6 +35,8 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Added YAML linting to CI - Added missing license headers and C header include guards - Extended the pre-commit hooks to remove trailing whitespace, check licenses, format and lint files +- Reshape operator support for PULP (`ReshapeTemplate` in bindings) +- Missing class attributes in `Closure.py` ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -57,12 +60,17 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Split CI into multiple workflow files: one per platform, one for lint & license, one for general Deeploy tests, one for infrastructure, and two for Docker flows, improving maintainability and status reporting - Extended CI to check license in cMake and YAML files - Removed all trailing whitespace +- Removed unnecessary includes from the PULP platform header list, such as `DeeployBasicMath.h`, for cleaner code generation +- Changed types and added correct casts to fix many compiler warnings in the PULP target library ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. - Fix license CI check and prevent potential issues with `jq` installation - PULP Gemm `batch` variable serialization +- Fixed multiple typos in variable and method names, such as changing `includeGobalReferences` to `includeGlobalReferences` and `dicardedMappers` to `discardedMappers` +- Corrected method usage in `importDeeployState` to call `NetworkContext.importNetworkContext` instead of the incorrect method name +- Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py index 8c1786dd5b..e256a7709e 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py @@ -85,7 +85,8 @@ def baseBlock(self): class ClosureGeneration(CodeTransformationPass, IntrospectiveCodeTransformationMixIn): - closureStructArgs: Struct + closureStructArgType: Dict[str, Type[Union[Pointer, Immediate, Struct]]] + closureStructArgs: Dict[str, Union[Pointer, Immediate, Struct]] def __init__(self, closureCallTemplate: NodeTemplate = _closureCallTemplate, diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py index 51d7dba617..fbb1d0b135 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py @@ -117,14 +117,14 @@ def extractDynamicReferences(self, ctxt: NetworkContext, executionBlock: ExecutionBlock = None, unrollStructs = False, - includeGobalReferences = False): + includeGlobalReferences = False): makoDynamicReferences = [] for codeSnippet in executionBlock.codeSnippets: template, operatorRepresentation = codeSnippet.template, codeSnippet.operatorRepresentation newRefs = self._extractDynamicExpressions(ctxt, operatorRepresentation, template.template, unrollStructs, - includeGobalReferences) + includeGlobalReferences) makoDynamicReferences += newRefs @@ -145,7 +145,7 @@ def _extractDynamicExpressions(self, operatorRepresentation: OperatorRepresentation, template: Template, unrollStructs = False, - includeGobalReferences = False): + includeGlobalReferences = False): codeHash = hash(template._source) if codeHash in self.parseTreeDict.keys(): @@ -194,7 +194,7 @@ def _unrollStructReferences(val: Struct) -> List[str]: dynamicLocalReferences = [ref for ref in localReferences if ctxt.lookup(ref)._deploy] dynamicGlobalReferences = [ref for ref in globalReferences if isinstance(ctxt.lookup(ref), VariableBuffer)] - if includeGobalReferences: + if includeGlobalReferences: return dynamicLocalReferences + dynamicGlobalReferences else: return dynamicLocalReferences diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py index 2293ded8e5..004565760f 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py @@ -117,7 +117,8 @@ def topologicallySortBuffers(buffers: List[VariableBuffer]) -> List[VariableBuff sortedBuffers.append(buffer) unsortedBufferNames.remove(buffer.name) - assert len(unsortedBufferNames) != lastLen, f"Circular reference detected." + assert len( + unsortedBufferNames) != lastLen, f"Circular reference detected among buffers: {unsortedBufferNames}" lastLen = len(unsortedBufferNames) return sortedBuffers @@ -130,7 +131,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = False) + includeGlobalReferences = False) localBuffers = [ctxt.localObjects[ref] for ref in references] memoryLevelBuffers = [buff for buff in localBuffers if self.is_memory_level(buff)] @@ -167,7 +168,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = False) + includeGlobalReferences = False) localBuffers = [ctxt.localObjects[ref] for ref in references] memoryLevelBuffers = [buff for buff in localBuffers if self.is_memory_level(buff)] diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py index 3144659959..5c2d212c07 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py @@ -83,7 +83,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) for ref in references: refDict = self._getRepDict(ctxt, ref, name) @@ -126,7 +126,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) filteredReferences = [ref for ref in references if self._matchesRegex(ctxt, ref)] @@ -167,7 +167,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) for ref in references: rep = self._getRepDict(ctxt, ref, name) @@ -188,7 +188,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) filteredReferences = [ref for ref in references if self._matchesRegex(ctxt, ref)] @@ -220,7 +220,7 @@ def apply(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) for ref in references: rep = self._getRepDict(ctxt, ref, name) @@ -241,7 +241,7 @@ def apply(self, references = self.extractDynamicReferences(ctxt, executionBlock, unrollStructs = True, - includeGobalReferences = True) + includeGlobalReferences = True) filteredReferences = [ref for ref in references if self._matchesRegex(ctxt, ref)] diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index f3281f1759..125d2a8ee8 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -1972,7 +1972,7 @@ def discardCurrentMapper(self): """Discard the current Mapper """ - self.dicardedMappers.add(self.mapper) + self.discardedMappers.add(self.mapper) self.mapper = None def resetDiscardedMappers(self): @@ -2124,7 +2124,7 @@ def bind(self, ctxt: NetworkContext) -> Tuple[NetworkContext, bool]: self.mapper.parser.operatorRepresentation['nodeOps'] = int(self.computeOps()) return newCtxt, True - self.discardedMappers.append(self.mapper) + self.discardedMappers.add(self.mapper) return ctxt, False def codeTransform(self, ctxt: NetworkContext, verbose: CodeGenVerbosity = _NoVerbosity) -> NetworkContext: @@ -3175,7 +3175,7 @@ def importDeeployState(self, folderPath: str, fileName: str): """ self.graph = NetworkDeployer._importONNXGraph(folderPath, f"{fileName}") - self.ctxt = NetworkContext.importNetworkCtxt(folderPath, f"{fileName}") + self.ctxt = NetworkContext.importNetworkContext(folderPath, f"{fileName}") class NetworkDeployer(NetworkContainer): diff --git a/Deeploy/Targets/PULPOpen/Bindings.py b/Deeploy/Targets/PULPOpen/Bindings.py index 5e13acf411..1898f00aff 100644 --- a/Deeploy/Targets/PULPOpen/Bindings.py +++ b/Deeploy/Targets/PULPOpen/Bindings.py @@ -31,7 +31,7 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.CodeTransformationPasses.Closure import ClosureGeneration, MemoryAwareClosureGeneration from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ - MemoryManagementGeneration + MemoryManagementGeneration, MemoryPassthroughGeneration from Deeploy.CommonExtensions.DataTypes import IntegerDataTypes, SignedIntegerDataTypes, float32_t, int8_t, int32_t, \ uint8_t from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeTemplate @@ -41,8 +41,8 @@ GatherTemplate, QuantTemplate, RQSiGELUTemplate, iHardswishTemplate from Deeploy.Targets.Generic.TypeCheckers import AddChecker, ConcatChecker, ConvChecker, DequantChecker, \ GatherChecker, GELUChecker, GEMMChecker, HardswishChecker, LayerNormChecker, MatMulChecker, MulChecker, \ - QuantChecker, ReduceMeanChecker, ReluChecker, RQAddChecker, RQHardswishChecker, SGDChecker, SliceChecker, \ - SoftmaxChecker, SoftmaxCrossEntropyLossChecker, TransposeChecker + QuantChecker, ReduceMeanChecker, ReluChecker, ReshapeChecker, RQAddChecker, RQHardswishChecker, SGDChecker, \ + SliceChecker, SoftmaxChecker, SoftmaxCrossEntropyLossChecker, TransposeChecker from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterSynch import PULPSynchCoresPass from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPClusterTiling import PULPClusterTiling from Deeploy.Targets.PULPOpen.CodeTransformationPasses.PULPL3Tiling import PULPL3Tiling @@ -53,8 +53,8 @@ from Deeploy.Targets.PULPOpen.Templates import ConvTemplate, FloatAddTemplate, FloatConvTemplate, FloatGELUTemplate, \ FloatGemmTemplate, FloatLayernormTemplate, FloatMatMulTemplate, FloatMaxPoolTemplate, FloatMulTemplate, \ FloatReluTemplate, FloatSoftmaxTemplate, GEMMTemplate, MatrixVectorTemplate, MaxPool2DTemplate, MulTemplate, \ - ReduceMeanTemplate, RequantShiftTemplate, RQAddTemplate, RQSiHardswishTemplate, SGDTemplate, SliceTemplate, \ - SoftmaxCrossEntropyLossTemplate, TallGEMMTemplate, TransposeTemplate, UniformRequantShiftTemplate, \ + ReduceMeanTemplate, RequantShiftTemplate, ReshapeTemplate, RQAddTemplate, RQSiHardswishTemplate, SGDTemplate, \ + SliceTemplate, SoftmaxCrossEntropyLossTemplate, TallGEMMTemplate, TransposeTemplate, UniformRequantShiftTemplate, \ iRMSNormTemplate, iSoftmaxTemplate from Deeploy.Targets.PULPOpen.TypeCheckers import PULPConvChecker, PULPLinearChecker, PULPMaxPoolChecker, \ PULPRequantShiftChecker @@ -76,6 +76,12 @@ pi_cl_team_fork(NUM_CORES, (void*)${closureName}, &${closureStructArgName}); """) +SkipTransformer = CodeTransformation( + [ArgumentStructGeneration(), + MemoryPassthroughGeneration("L.*"), + MemoryPassthroughGeneration(), + FutureGeneration()]) + FunctionCallClosure = partial(ClosureGeneration, closureSuffix = "_closure") ClusterClosure = partial(ClosureGeneration, closureSuffix = "_cluster_entry", @@ -169,6 +175,14 @@ for type in IntegerDataTypes ] +PULPReshapeBindings = [ + NodeBinding(ReshapeChecker([PointerClass(type), PointerClass(int32_t)], [PointerClass(type)]), + ReshapeTemplate.referenceTemplate, SkipTransformer) for type in IntegerDataTypes +] + [ + NodeBinding(ReshapeChecker([PointerClass(float32_t), PointerClass(type)], [PointerClass(float32_t)]), + ReshapeTemplate.referenceTemplate, SkipTransformer) for type in IntegerDataTypes +] + PULPRQAddBindings = [ NodeBinding(RQAddChecker([PointerClass(_type), PointerClass(_type2)], [PointerClass(_type3)]), RQAddTemplate.referenceTemplate, ForkTransformer) diff --git a/Deeploy/Targets/PULPOpen/Platform.py b/Deeploy/Targets/PULPOpen/Platform.py index 2fded86717..fd014e82c6 100644 --- a/Deeploy/Targets/PULPOpen/Platform.py +++ b/Deeploy/Targets/PULPOpen/Platform.py @@ -253,8 +253,7 @@ class PULPStructBuffer(StructBuffer): # SCHEREMO: stdint is included before pulp_nn_kernels.h because it is supposed to be included in there, but isn't... _includeList = [ - "pmsis.h", "stdint.h", "pulp_nn_kernels.h", "DeeployBasicMath.h", "DeeployPULPMath.h", "mchan_siracusa.h", - "dory_mem.h", "bsp/ram.h", "pulp_core.h" + "pmsis.h", "stdint.h", "pulp_nn_kernels.h", "DeeployPULPMath.h", "mchan_siracusa.h", "dory_mem.h", "bsp/ram.h" ] diff --git a/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py b/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py new file mode 100644 index 0000000000..41c4b5366c --- /dev/null +++ b/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py @@ -0,0 +1,59 @@ +# ---------------------------------------------------------------------- +# +# File: ReshapeTemplate.py +# +# Last edited: 16.12.2021 +# +# Copyright (C) 2021, ETH Zurich and University of Bologna. +# +# Author: Moritz Scherer, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, List, Tuple + +from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation + + +class _ReshapeTemplate(NodeTemplate): + + def __init__(self, templateStr): + super().__init__(templateStr) + + def alignToContext(self, ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict, List[str]]: + + # SCHEREMO: Selectively mark 'indices' dead, since we don't need them + if 'indices' in operatorRepresentation.keys(): + ctxt.globalObjects[operatorRepresentation['indices']]._deploy = False + ctxt.globalObjects[operatorRepresentation['indices']]._live = False + + # Same for "shape" + if "shape" in operatorRepresentation.keys(): + ctxt.globalObjects[operatorRepresentation["shape"]]._deploy = False + ctxt.globalObjects[operatorRepresentation["shape"]]._live = False + + inBuffer = ctxt.lookup(operatorRepresentation['data_in']) + outBuffer = ctxt.lookup(operatorRepresentation['data_out']) + outBuffer._alias = inBuffer.name + + return ctxt, operatorRepresentation, [] + + +referenceTemplate = _ReshapeTemplate(""" +// Reshape (Name: ${nodeName}, Op: ${nodeOp}) +${data_out} = ${data_in}; +""") diff --git a/Deeploy/Targets/PULPOpen/Tiler.py b/Deeploy/Targets/PULPOpen/Tiler.py index 62c8090c16..dbca111478 100644 --- a/Deeploy/Targets/PULPOpen/Tiler.py +++ b/Deeploy/Targets/PULPOpen/Tiler.py @@ -26,9 +26,6 @@ import copy -from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import MemoryPassthroughGeneration -from Deeploy.DeeployTypes import CodeTransformation -from Deeploy.Targets.Generic.Bindings import BasicReshapeBindings from Deeploy.Targets.Generic.TileConstraints.AddTileConstraint import AddTileConstraint from Deeploy.Targets.Generic.TileConstraints.ConcatTileConstraint import ConcatTileConstraint from Deeploy.Targets.Generic.TileConstraints.iHardswishTileConstraint import iHardswishTileConstraint @@ -43,10 +40,11 @@ from Deeploy.Targets.PULPOpen.Bindings import PULPAddBindings, PULPConcatBindings, PULPFloatConv2DBindings, \ PULPFloatGELUBinding, PULPFloatGEMMBindings, PULPGatherBindings, PULPiHardswishBindings, PULPiRMSNormBindings, \ PULPiRQSGELUBindings, PULPLayernormBinding, PULPMatMulBindings, PULPMaxPool2DBindings, PULPMulBindings, \ - PULPReduceSumBindings, PULPReluBinding, PULPRQAddBindings, PULPRQSBindings, PULPRQSConv2DBindings, \ - PULPRQSDWConv2DBindings, PULPRQSGEMMBindings, PULPRQSiHardswishBindings, PULPRQSMatrixVecBindings, \ - PULPRQSTallGEMMBindings, PULPSGDBindings, PULPSoftmaxBindings, PULPSoftmaxCrossEntropyLossBindings, \ - PULPSoftmaxCrossEntropyLossGradBindings, PULPSoftmaxGradBindings, PULPTransposeBindings, PULPUniformRQSBindings + PULPReduceSumBindings, PULPReluBinding, PULPReshapeBindings, PULPRQAddBindings, PULPRQSBindings, \ + PULPRQSConv2DBindings, PULPRQSDWConv2DBindings, PULPRQSGEMMBindings, PULPRQSiHardswishBindings, \ + PULPRQSMatrixVecBindings, PULPRQSTallGEMMBindings, PULPSGDBindings, PULPSoftmaxBindings, \ + PULPSoftmaxCrossEntropyLossBindings, PULPSoftmaxCrossEntropyLossGradBindings, PULPSoftmaxGradBindings, \ + PULPTransposeBindings, PULPUniformRQSBindings from Deeploy.Targets.PULPOpen.TileConstraints.ConvTileConstraint import Conv2DTileConstraint, RQConv2DTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.DWConvTileConstraint import DWConv2DTileConstraint from Deeploy.Targets.PULPOpen.TileConstraints.GatherTileConstraint import GatherTileConstraint @@ -94,9 +92,7 @@ PULPRQSiHardswishTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = PULPRQSiHardswishBindings, tileConstraint = RQSiHardswishTileConstraint()) -_BasicFlattenBindings = copy.deepcopy(BasicReshapeBindings) -for binding in _BasicFlattenBindings: - binding.codeTransformer = CodeTransformation([MemoryPassthroughGeneration("L.*"), MemoryPassthroughGeneration()]) +_BasicFlattenBindings = copy.deepcopy(PULPReshapeBindings) PULPFlattenTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = _BasicFlattenBindings, tileConstraint = NOPTileConstraint()) diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py index 5dc9c11eeb..9108ab5024 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py @@ -67,7 +67,9 @@ class TilingMetaInfo: _printLoopSetup = NodeTemplate(""" StopTimer(); -for (int ${profileIdxVar} = ${numTiles}[*${tileIdxPtr} -1]; ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; ${profileIdxVar}++){ +for (int ${profileIdxVar} = ((*${tileIdxPtr} > 0) ? ${numTiles}[(*${tileIdxPtr} - 1)] : 0); + ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; + ${profileIdxVar}++){ """) _printCycleDifference = NodeTemplate(r""" diff --git a/DeeployTest/Platforms/PULPOpen/src/deeploytest.c b/DeeployTest/Platforms/PULPOpen/src/deeploytest.c index 525852d8d5..26457c3d8d 100644 --- a/DeeployTest/Platforms/PULPOpen/src/deeploytest.c +++ b/DeeployTest/Platforms/PULPOpen/src/deeploytest.c @@ -9,6 +9,7 @@ * Copyright (C) 2020 ETH Zurich and University of Bologna. * * Author: Moritz Scherer, ETH Zurich + * Author: Run Wang, ETH Zurich * * SPDX-License-Identifier: Apache-2.0 * @@ -32,82 +33,160 @@ #include "testinputs.h" #include "testoutputs.h" +#define MAINSTACKSIZE 8000 +#define SLAVESTACKSIZE 3800 + struct pi_device cluster_dev; -void main(void) { +typedef struct { + void *expected; + void *actual; + uint32_t num_elements; + uint32_t output_buf_index; + uint32_t *err_count; +} FloatCompareArgs; + +void CompareFloatOnCluster(void *args) { + + if (pi_core_id() == 0) { + FloatCompareArgs *compare_args = (FloatCompareArgs *)args; + float *expected = (float *)compare_args->expected; + float *actual = (float *)compare_args->actual; + uint32_t num_elements = compare_args->num_elements; + uint32_t output_buf_index = compare_args->output_buf_index; + uint32_t *err_count = compare_args->err_count; + + uint32_t local_err_count = 0; + + for (uint32_t i = 0; i < num_elements; i++) { + float expected_val = expected[i]; + float actual_val = actual[i]; + float diff = expected_val - actual_val; + + if ((diff < -1e-4) || (diff > 1e-4) || isnan(diff)) { + local_err_count += 1; + + printf("Expected: %10.6f ", expected_val); + printf("Actual: %10.6f ", actual_val); + printf("Diff: %10.6f at Index %12u in Output %u\r\n", diff, i, + output_buf_index); + } + } + + *err_count = local_err_count; + } +} + +int main(void) { #ifndef CI printf("HELLO WORLD:\r\n"); #endif - struct pi_cluster_conf conf; pi_cluster_conf_init(&conf); conf.id = 0; pi_open_from_conf(&cluster_dev, &conf); if (pi_cluster_open(&cluster_dev)) - return; + return -1; - struct pi_cluster_task cluster_task_mem_init; + mem_init(); +#ifndef NOFLASH + open_fs(); +#endif - pi_cluster_task(&cluster_task_mem_init, mem_init, NULL); - cluster_task_mem_init.stack_size = 5000; - cluster_task_mem_init.slave_stack_size = 3800; - pi_cluster_send_task_to_cl(&cluster_dev, &cluster_task_mem_init); + printf("Intializing\r\n"); struct pi_cluster_task cluster_task; pi_cluster_task(&cluster_task, InitNetwork, NULL); - cluster_task.stack_size = 5000; - cluster_task.slave_stack_size = 3800; + cluster_task.stack_size = MAINSTACKSIZE; + cluster_task.slave_stack_size = SLAVESTACKSIZE; pi_cluster_send_task_to_cl(&cluster_dev, &cluster_task); #ifndef CI printf("Initialized\r\n"); #endif - for (int buf = 0; buf < DeeployNetwork_num_inputs; buf++) { - memcpy(DeeployNetwork_inputs[buf], testInputVector[buf], - DeeployNetwork_inputs_bytes[buf]); + for (uint32_t buf = 0; buf < DeeployNetwork_num_inputs; buf++) { + if ((uint32_t)DeeployNetwork_inputs[buf] >= 0x10000000) { + memcpy(DeeployNetwork_inputs[buf], testInputVector[buf], + DeeployNetwork_inputs_bytes[buf]); + } } + #ifndef CI printf("Input copied\r\n"); #endif - ResetTimer(); - StartTimer(); - // RunNetwork(0, 1); pi_cluster_task(&cluster_task, RunNetwork, NULL); - cluster_task.stack_size = 5000; - cluster_task.slave_stack_size = 3800; + cluster_task.stack_size = MAINSTACKSIZE; + cluster_task.slave_stack_size = SLAVESTACKSIZE; + ResetTimer(); + StartTimer(); pi_cluster_send_task_to_cl(&cluster_dev, &cluster_task); -#ifndef CI - printf("Run\r\n"); -#endif StopTimer(); + #ifndef CI printf("Output:\r\n"); #endif - int32_t diff, tot_err; + + uint32_t tot_err, tot_tested; tot_err = 0; - for (int buf = 0; buf < DeeployNetwork_num_outputs; buf++) { - for (int i = 0; i < DeeployNetwork_outputs_bytes[buf]; i++) { - diff = ((char *)testOutputVector[buf])[i] - - ((char *)DeeployNetwork_outputs[buf])[i]; - if (diff) { - tot_err += 1; -#ifndef CI - printf("Expected: %i\t\t", ((int8_t *)testOutputVector[buf])[i]); - printf("Actual: %i \t\t", ((int8_t *)DeeployNetwork_outputs[buf])[i]); -#endif -#ifndef CI - printf("Diff: %i at Index %u \r\n", diff, i); -#endif - } else { - /* #ifndef CI */ - /* printf("\r\n"); */ - /* #endif */ + tot_tested = 0; + void *compbuf; + FloatCompareArgs float_compare_args; + uint32_t float_error_count = 0; + + for (uint32_t buf = 0; buf < DeeployNetwork_num_outputs; buf++) { + tot_tested += DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); + + if ((uint32_t)DeeployNetwork_outputs[buf] < 0x1000000) { + compbuf = pi_l2_malloc((int)DeeployNetwork_outputs_bytes[buf]); + ram_read(compbuf, DeeployNetwork_outputs[buf], + DeeployNetwork_outputs_bytes[buf]); + } else { + compbuf = DeeployNetwork_outputs[buf]; + } + + if (ISOUTPUTFLOAT) { + float_error_count = 0; + float_compare_args.expected = testOutputVector[buf]; + float_compare_args.actual = compbuf; + float_compare_args.num_elements = + DeeployNetwork_outputs_bytes[buf] / sizeof(float); + float_compare_args.output_buf_index = buf; + float_compare_args.err_count = &float_error_count; + + pi_cluster_task(&cluster_task, CompareFloatOnCluster, + &float_compare_args); + cluster_task.stack_size = MAINSTACKSIZE; + cluster_task.slave_stack_size = SLAVESTACKSIZE; + pi_cluster_send_task_to_cl(&cluster_dev, &cluster_task); + + tot_err += float_error_count; + } else { + + for (uint32_t i = 0; + i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { + OUTPUTTYPE expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; + OUTPUTTYPE actual = ((OUTPUTTYPE *)compbuf)[i]; + int32_t error = expected - actual; + OUTPUTTYPE diff = (OUTPUTTYPE)(error < 0 ? -error : error); + + if (diff) { + tot_err += 1; + printf("Expected: %4d ", expected); + printf("Actual: %4d ", actual); + printf("Diff: %4d at Index %12u in Output %u\r\n", diff, i, buf); + } } } + if ((uint32_t)DeeployNetwork_outputs[buf] < 0x1000000) { + pi_l2_free(compbuf, (int)DeeployNetwork_outputs_bytes[buf]); + } } + printf("Runtime: %u cycles\r\n", getCycles()); - printf("Errors: %u out of %u \r\n", tot_err, DeeployNetwork_output_0_len); -} + printf("Errors: %u out of %u \r\n", tot_err, tot_tested); + + return (int)tot_err; +} \ No newline at end of file diff --git a/DeeployTest/Platforms/Siracusa/src/deeploytest.c b/DeeployTest/Platforms/Siracusa/src/deeploytest.c index 8ed6952c72..26457c3d8d 100644 --- a/DeeployTest/Platforms/Siracusa/src/deeploytest.c +++ b/DeeployTest/Platforms/Siracusa/src/deeploytest.c @@ -41,9 +41,9 @@ struct pi_device cluster_dev; typedef struct { void *expected; void *actual; - int num_elements; - int output_buf_index; - int *err_count; + uint32_t num_elements; + uint32_t output_buf_index; + uint32_t *err_count; } FloatCompareArgs; void CompareFloatOnCluster(void *args) { @@ -52,13 +52,13 @@ void CompareFloatOnCluster(void *args) { FloatCompareArgs *compare_args = (FloatCompareArgs *)args; float *expected = (float *)compare_args->expected; float *actual = (float *)compare_args->actual; - int num_elements = compare_args->num_elements; - int output_buf_index = compare_args->output_buf_index; - int *err_count = compare_args->err_count; + uint32_t num_elements = compare_args->num_elements; + uint32_t output_buf_index = compare_args->output_buf_index; + uint32_t *err_count = compare_args->err_count; - int local_err_count = 0; + uint32_t local_err_count = 0; - for (int i = 0; i < num_elements; i++) { + for (uint32_t i = 0; i < num_elements; i++) { float expected_val = expected[i]; float actual_val = actual[i]; float diff = expected_val - actual_val; @@ -77,7 +77,7 @@ void CompareFloatOnCluster(void *args) { } } -void main(void) { +int main(void) { #ifndef CI printf("HELLO WORLD:\r\n"); #endif @@ -87,7 +87,7 @@ void main(void) { conf.id = 0; pi_open_from_conf(&cluster_dev, &conf); if (pi_cluster_open(&cluster_dev)) - return; + return -1; mem_init(); #ifndef NOFLASH @@ -106,8 +106,8 @@ void main(void) { #ifndef CI printf("Initialized\r\n"); #endif - for (int buf = 0; buf < DeeployNetwork_num_inputs; buf++) { - if (DeeployNetwork_inputs[buf] >= 0x10000000) { + for (uint32_t buf = 0; buf < DeeployNetwork_num_inputs; buf++) { + if ((uint32_t)DeeployNetwork_inputs[buf] >= 0x10000000) { memcpy(DeeployNetwork_inputs[buf], testInputVector[buf], DeeployNetwork_inputs_bytes[buf]); } @@ -116,7 +116,7 @@ void main(void) { #ifndef CI printf("Input copied\r\n"); #endif - // RunNetwork(0, 1); + pi_cluster_task(&cluster_task, RunNetwork, NULL); cluster_task.stack_size = MAINSTACKSIZE; cluster_task.slave_stack_size = SLAVESTACKSIZE; @@ -136,11 +136,11 @@ void main(void) { FloatCompareArgs float_compare_args; uint32_t float_error_count = 0; - for (int buf = 0; buf < DeeployNetwork_num_outputs; buf++) { + for (uint32_t buf = 0; buf < DeeployNetwork_num_outputs; buf++) { tot_tested += DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); - if (DeeployNetwork_outputs[buf] < 0x1000000) { - compbuf = pi_l2_malloc(DeeployNetwork_outputs_bytes[buf]); + if ((uint32_t)DeeployNetwork_outputs[buf] < 0x1000000) { + compbuf = pi_l2_malloc((int)DeeployNetwork_outputs_bytes[buf]); ram_read(compbuf, DeeployNetwork_outputs[buf], DeeployNetwork_outputs_bytes[buf]); } else { @@ -165,11 +165,11 @@ void main(void) { tot_err += float_error_count; } else { - for (int i = 0; + for (uint32_t i = 0; i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { OUTPUTTYPE expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; OUTPUTTYPE actual = ((OUTPUTTYPE *)compbuf)[i]; - int error = expected - actual; + int32_t error = expected - actual; OUTPUTTYPE diff = (OUTPUTTYPE)(error < 0 ? -error : error); if (diff) { @@ -180,11 +180,13 @@ void main(void) { } } } - if (DeeployNetwork_outputs[buf] < 0x1000000) { - pi_l2_free(compbuf, DeeployNetwork_outputs_bytes[buf]); + if ((uint32_t)DeeployNetwork_outputs[buf] < 0x1000000) { + pi_l2_free(compbuf, (int)DeeployNetwork_outputs_bytes[buf]); } } printf("Runtime: %u cycles\r\n", getCycles()); printf("Errors: %u out of %u \r\n", tot_err, tot_tested); + + return (int)tot_err; } \ No newline at end of file diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index a50ff739ea..ecca6266c9 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -26,7 +26,7 @@ import os import sys from collections import OrderedDict -from typing import List +from typing import List, Tuple import numpy as np import onnx @@ -76,7 +76,7 @@ def _filterSchedule(schedule: List[List[gs.Node]], layerBinding: 'OrderedDict[st def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTargetMemoryLevel: MemoryLevel, - defaultIoMemoryLevel: MemoryLevel, verbose: CodeGenVerbosity) -> NetworkDeployer: + defaultIoMemoryLevel: MemoryLevel, verbose: CodeGenVerbosity) -> Tuple[NetworkDeployer, bool]: inputTypes = {} inputOffsets = {} @@ -143,7 +143,7 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg deployer.tiler.memoryAllocStrategy = args.memAllocStrategy deployer.tiler.searchStrategy = args.searchStrategy - return deployer + return deployer, signProp if __name__ == '__main__': @@ -263,14 +263,13 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg memoryHierarchy = MemoryHierarchy(memoryLevels) memoryHierarchy.setDefaultMemoryLevel(args.defaultMemLevel) - deployer = setupDeployer(graph, - memoryHierarchy, - defaultTargetMemoryLevel = L1, - defaultIoMemoryLevel = memoryHierarchy.memoryLevels[args.defaultMemLevel], - verbose = verbosityCfg) + deployer, signProp = setupDeployer(graph, + memoryHierarchy, + defaultTargetMemoryLevel = L1, + defaultIoMemoryLevel = memoryHierarchy.memoryLevels[args.defaultMemLevel], + verbose = verbosityCfg) platform = deployer.Platform - signProp = False for index, num in enumerate(test_inputs): _type, offset = inferTypeAndOffset(num, signProp) diff --git a/DeeployTest/testRunner_tiled_siracusa.py b/DeeployTest/testRunner_tiled_siracusa.py index 827affbeb5..cea732f3d5 100644 --- a/DeeployTest/testRunner_tiled_siracusa.py +++ b/DeeployTest/testRunner_tiled_siracusa.py @@ -28,8 +28,7 @@ if __name__ == "__main__": parser = TestRunnerArgumentParser( - tiling_arguments = True, - description = "Deeploy Code Generation Utility for the Siracusa Platform (Tiling & NEureka).") + tiling_arguments = True, description = "Deeploy Code Generation Utility for the Siracusa Platform (Tiling).") parser.add_argument('--cores', metavar = '', diff --git a/DeeployTest/testUtils/codeGenerate.py b/DeeployTest/testUtils/codeGenerate.py index eb148ad2be..c873e447ca 100644 --- a/DeeployTest/testUtils/codeGenerate.py +++ b/DeeployTest/testUtils/codeGenerate.py @@ -30,6 +30,7 @@ from Deeploy.DeeployTypes import CodeGenVerbosity, ConstantBuffer, NetworkDeployer, VariableBuffer from Deeploy.Targets.MemPool.Platform import MemPoolPlatform +from Deeploy.Targets.PULPOpen.Platform import MemoryPULPPlatform, MemoryPULPPlatformWrapper, PULPPlatform _TEXT_ALIGN = 30 @@ -81,12 +82,11 @@ def generateTestInputsHeader(deployer: NetworkDeployer, test_inputs: List) -> st list_str = (", ").join([str(x) for x in values]) # WIESEP: Arrays have to be 4 byte aligned (at least in banshee) - bytes = (len(values) * typeWidth) // 8 - if bytes % 4 != 0: - paddingBytes = bytes % 4 - paddingElements = paddingBytes * 8 // typeWidth - list_str += ", " - list_str += (", ").join([str(0) for _ in range(paddingElements)]) + total_bytes = (values.size * typeWidth) // 8 + pad_bytes = (-total_bytes) % 4 + if pad_bytes: + paddingElements = (pad_bytes * 8 + typeWidth - 1) // typeWidth + list_str += ", " + (", ").join("0" for _ in range(paddingElements)) retStr += list_str retStr += "};\n" @@ -116,12 +116,11 @@ def generateTestOutputsHeader(deployer: NetworkDeployer, test_outputs: List[np.n list_str = (", ").join([str(x) for x in values]) # WIESEP: Arrays have to be 4 byte aligned (at least in banshee) - bytes = (len(values) * typeWidth) // 8 - if bytes % 4 != 0: - paddingBytes = bytes % 4 - paddingElements = paddingBytes * 8 // typeWidth - list_str += ", " - list_str += (", ").join([str(0) for _ in range(paddingElements)]) + total_bytes = (len(values) * typeWidth) // 8 + pad_bytes = (-total_bytes) % 4 + if pad_bytes: + paddingElements = (pad_bytes * 8 + typeWidth - 1) // typeWidth + list_str += ", " + (", ").join("0" for _ in range(paddingElements)) retStr += list_str retStr += "};\n" @@ -144,11 +143,18 @@ def generateTestNetworkHeader(deployer: NetworkDeployer) -> str: #include """ retStr += deployer.generateIncludeString() - retStr += """ - void RunNetwork(uint32_t core_id, uint32_t numThreads); - void InitNetwork(uint32_t core_id, uint32_t numThread); + if isinstance(deployer.Platform, (PULPPlatform, MemoryPULPPlatform, MemoryPULPPlatformWrapper)): + retStr += """ + void RunNetwork(); + void InitNetwork(); - """ + """ + else: + retStr += """ + void RunNetwork(uint32_t core_id, uint32_t numThreads); + void InitNetwork(uint32_t core_id, uint32_t numThread); + + """ retStr += deployer.generateIOBufferInitializationCode() retStr += """ @@ -181,6 +187,11 @@ def generateTestNetworkImplementation(deployer: NetworkDeployer, verbosityCfg: C retStr += """ void RunNetwork(__attribute__((unused)) uint32_t core_id, __attribute__((unused)) uint32_t numThreads){ """ + elif isinstance(deployer.Platform, (PULPPlatform, MemoryPULPPlatform, MemoryPULPPlatformWrapper)): + retStr += """ + void RunNetwork(){ + """ + retStr += deployer.generateInferenceInitializationCode() else: retStr += """ void RunNetwork(__attribute__((unused)) uint32_t core_id, __attribute__((unused)) uint32_t numThreads){ @@ -188,11 +199,18 @@ def generateTestNetworkImplementation(deployer: NetworkDeployer, verbosityCfg: C retStr += deployer.generateInferenceInitializationCode() retStr += deployer.generateFunction(verbosityCfg) - retStr += """ - } + if isinstance(deployer.Platform, (PULPPlatform, MemoryPULPPlatform, MemoryPULPPlatformWrapper)): + retStr += """ + } - void InitNetwork(__attribute__((unused)) uint32_t core_id, __attribute__((unused)) uint32_t numThreads){ - """ + void InitNetwork(){ + """ + else: + retStr += """ + } + + void InitNetwork(__attribute__((unused)) uint32_t core_id, __attribute__((unused)) uint32_t numThreads){ + """ retStr += deployer.generateEngineInitializationCode() retStr += deployer.generateBufferAllocationCode() retStr += """ diff --git a/README.md b/README.md index bbb5fdba0a..22b1ccd45d 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ [![Documentation Status](https://img.shields.io/github/deployments/pulp-platform/Deeploy/github-pages?logo=readthedocs&logoColor=white&label=Docs )](https://pulp-platform.github.io/Deeploy/) [![CI](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml) -![Deeploy Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/BuildDockerDeeploy.yml/badge.svg) -![Toolchain Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/BuildDockerToolchain.yml/badge.svg) +[![Deeploy Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/docker-build-deeploy.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/docker-build-deeploy.yml) [![GitHub last commit](https://img.shields.io/github/last-commit/pulp-platform/Deeploy)](#) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/Provided_by_PULP_Platform-24AF4B) diff --git a/TargetLibraries/PULPOpen/CMakeLists.txt b/TargetLibraries/PULPOpen/CMakeLists.txt index d0c24858ca..fde35caec3 100644 --- a/TargetLibraries/PULPOpen/CMakeLists.txt +++ b/TargetLibraries/PULPOpen/CMakeLists.txt @@ -29,6 +29,11 @@ target_compile_options(deeploypulp PRIVATE -Wno-implicit-int-conversion -Wno-sign-conversion -Wno-sign-compare + -Wno-typedef-redefinition + -Wno-unused-parameter + -Wno-unused-function + -Wno-unused-variable + -Wno-uninitialized ) target_include_directories(deeploypulp PUBLIC ${PULP_SDK_INCLUDES}) @@ -52,5 +57,12 @@ if (platform IN_LIST PULP_NNX_PLATFORMS) add_subdirectory(third_party/pulp-nnx) target_include_directories(pulp-nnx PUBLIC ${PULP_SDK_INCLUDES}) target_compile_options(pulp-nnx PUBLIC ${PULP_SDK_COMPILE_FLAGS}) + target_compile_options(pulp-nnx PRIVATE + -Wno-implicit-int-conversion + -Wno-sign-conversion + -Wno-typedef-redefinition + -Wno-unused-parameter + -Wno-incompatible-pointer-types-discards-qualifiers + ) target_link_libraries(deeploypulp INTERFACE pulp-nnx) endif() diff --git a/TargetLibraries/PULPOpen/inc/DeeployMath.h b/TargetLibraries/PULPOpen/inc/DeeployMath.h deleted file mode 100644 index 7aa1b1805c..0000000000 --- a/TargetLibraries/PULPOpen/inc/DeeployMath.h +++ /dev/null @@ -1,45 +0,0 @@ -/* ===================================================================== - * Title: DeeployMath.h - * Description: - * - * $Date: 30.12.2021 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __DEEPLOY_MATH_HEADER_ -#define __DEEPLOY_MATH_HEADER_ - -#include -#include -#include -#include -#include - -#if defined(AM_PART_APOLLO4B) | defined(DAM_PART_APOLLO3) -#include "am_bsp.h" -#include "am_mcu_apollo.h" -#include "am_util.h" -#endif - -#include "DeeployBasicMath.h" - -#endif // __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h b/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h index a9d242d1b3..5e5b4142cb 100644 --- a/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h +++ b/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h @@ -36,6 +36,10 @@ #include "types.h" +#define BEGIN_SINGLE_CORE if (pi_core_id() == 0) { +#define END_SINGLE_CORE } +#define SINGLE_CORE if (pi_core_id() == 0) + #include "DeeployBasicMath.h" #include "pmsis.h" @@ -52,4 +56,6 @@ #include "kernel/gemv.h" #include "kernel/iRMSnorm.h" +#define LOG2(x) (__builtin_pulp_fl1(x)) + #endif // __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/PULPOpen/src/Convolution_fp32.c b/TargetLibraries/PULPOpen/src/Convolution_fp32.c index 43ec7f4b5d..c62d449d65 100644 --- a/TargetLibraries/PULPOpen/src/Convolution_fp32.c +++ b/TargetLibraries/PULPOpen/src/Convolution_fp32.c @@ -40,7 +40,7 @@ void PULP_Conv2d_fp32_fp32_fp32_HWC(const float32_t *__restrict__ pSrcA, uint32_t pad_left, uint32_t pad_right) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); uint16_t ch_out_chunk = (F_total >> log2Core) + ((F_total & (NUM_CORES - 1)) != 0); @@ -95,7 +95,7 @@ void PULP_Conv2d_Im2Col_fp32_fp32_fp32_HWC( uint32_t pad_top, uint32_t pad_bottom, uint32_t pad_left, uint32_t pad_right, float32_t *__restrict__ pContextBuffer) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); uint16_t ch_out_chunk = (F_total >> log2Core) + ((F_total & (NUM_CORES - 1)) != 0); diff --git a/TargetLibraries/PULPOpen/src/GELU.c b/TargetLibraries/PULPOpen/src/GELU.c index a128645638..80d0cd933c 100644 --- a/TargetLibraries/PULPOpen/src/GELU.c +++ b/TargetLibraries/PULPOpen/src/GELU.c @@ -28,8 +28,6 @@ */ #include "pmsis.h" -#include "pulp_nn_kernels.h" -#include "pulp_nn_utils.h" #include "DeeployPULPMath.h" @@ -38,7 +36,7 @@ void PULP_GELU_fp32_fp32(float32_t *data_in, float32_t *data_out, int32_t dataSize) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (dataSize >> log2Core) + ((dataSize & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, dataSize); int16_t chunk_stop = MIN(chunk_start + chunk, dataSize); @@ -61,7 +59,7 @@ void PULP_GELU_fp32_fp32(float32_t *data_in, float32_t *data_out, void PULP_GELU_fp32_fp32_sigmoid(float32_t *data_in, float32_t *data_out, int32_t dataSize) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (dataSize >> log2Core) + ((dataSize & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, dataSize); int16_t chunk_stop = MIN(chunk_start + chunk, dataSize); diff --git a/TargetLibraries/PULPOpen/src/Gemm.c b/TargetLibraries/PULPOpen/src/Gemm.c index 58d1688a46..d1a21f976f 100644 --- a/TargetLibraries/PULPOpen/src/Gemm.c +++ b/TargetLibraries/PULPOpen/src/Gemm.c @@ -39,7 +39,7 @@ void PULP_Gemm_fp32_fp32_fp32_fp32(const float32_t *__restrict__ pSrcA, uint32_t transB) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); uint32_t M_chunk = (M >> log2Core) + ((M & (NUM_CORES - 1)) != 0); uint32_t M_start = MIN(core_id * M_chunk, M); diff --git a/TargetLibraries/PULPOpen/src/Layernorm.c b/TargetLibraries/PULPOpen/src/Layernorm.c index ca2d977399..8cd10c37af 100644 --- a/TargetLibraries/PULPOpen/src/Layernorm.c +++ b/TargetLibraries/PULPOpen/src/Layernorm.c @@ -29,8 +29,6 @@ */ #include "pmsis.h" -#include "pulp_nn_kernels.h" -#include "pulp_nn_utils.h" #include "DeeployPULPMath.h" @@ -40,7 +38,7 @@ void PULP_Layernorm_fp32_fp32(float32_t *data_in, float32_t *data_out, uint32_t lastDimLength) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int32_t seq_length = size / lastDimLength; int32_t chunk = diff --git a/TargetLibraries/PULPOpen/src/Matmul.c b/TargetLibraries/PULPOpen/src/Matmul.c index ba2f235851..252c0df377 100644 --- a/TargetLibraries/PULPOpen/src/Matmul.c +++ b/TargetLibraries/PULPOpen/src/Matmul.c @@ -29,8 +29,6 @@ */ #include "pmsis.h" -#include "pulp_nn_kernels.h" -#include "pulp_nn_utils.h" #include "DeeployPULPMath.h" @@ -40,7 +38,7 @@ void PULP_MatMul_fp32_fp32_fp32_unroll1x7(const float32_t *__restrict__ pSrcA, uint32_t M, uint32_t N, uint32_t O) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); uint32_t M_chunk = (M >> log2Core) + ((M & (NUM_CORES - 1)) != 0); uint32_t M_start = MIN(core_id * M_chunk, M); diff --git a/TargetLibraries/PULPOpen/src/MaxPool.c b/TargetLibraries/PULPOpen/src/MaxPool.c index 3ccea4cfbd..8490bae031 100644 --- a/TargetLibraries/PULPOpen/src/MaxPool.c +++ b/TargetLibraries/PULPOpen/src/MaxPool.c @@ -38,7 +38,7 @@ void PULP_MaxPool2d_fp32_fp32_HWC(const float32_t *__restrict__ pSrcA, uint32_t pad_left, uint32_t pad_right) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); uint16_t ch_chunk = (C >> log2Core) + ((C & (NUM_CORES - 1)) != 0); uint16_t ch_start = MIN(ch_chunk * core_id, C); diff --git a/TargetLibraries/PULPOpen/src/RQiHardswish.c b/TargetLibraries/PULPOpen/src/RQiHardswish.c index 8689383c0d..c9a79e6f80 100644 --- a/TargetLibraries/PULPOpen/src/RQiHardswish.c +++ b/TargetLibraries/PULPOpen/src/RQiHardswish.c @@ -37,7 +37,7 @@ void RQiHardswish_s8_s8_plp(int8_t *input, int8_t *output, int32_t size, rnd = (1 << (shift - 1)); int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, size); int16_t chunk_stop = MIN(chunk_start + chunk, size + 1); diff --git a/TargetLibraries/PULPOpen/src/Relu.c b/TargetLibraries/PULPOpen/src/Relu.c index a446ac60c5..bb003066af 100644 --- a/TargetLibraries/PULPOpen/src/Relu.c +++ b/TargetLibraries/PULPOpen/src/Relu.c @@ -34,7 +34,7 @@ void PULP_Relu_fp32_fp32(float32_t *input, float32_t *output, uint32_t size) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int32_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int32_t start = MIN(chunk * core_id, size); diff --git a/TargetLibraries/PULPOpen/src/Softmax.c b/TargetLibraries/PULPOpen/src/Softmax.c index f6370f35e8..9b8244d65a 100644 --- a/TargetLibraries/PULPOpen/src/Softmax.c +++ b/TargetLibraries/PULPOpen/src/Softmax.c @@ -127,7 +127,7 @@ void PULP_Softmax_fp32_fp32(float32_t *input, float32_t *output, uint32_t size, uint32_t last_dim_length) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int32_t num_vectors = size / last_dim_length; int32_t chunk = diff --git a/TargetLibraries/PULPOpen/src/UniformRequantShift.c b/TargetLibraries/PULPOpen/src/UniformRequantShift.c index 5507d0ebbc..202bb14444 100644 --- a/TargetLibraries/PULPOpen/src/UniformRequantShift.c +++ b/TargetLibraries/PULPOpen/src/UniformRequantShift.c @@ -34,7 +34,7 @@ void UniformRequantShift_s8_s8(int8_t *data_in, int32_t size, int32_t mul, int8_t output_max, bool rounding) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, size); int16_t chunk_stop = MIN(chunk_start + chunk, size + 1); @@ -99,7 +99,7 @@ void UniformRequantShift_u8_s8(uint8_t *data_in, int32_t size, int32_t mul, int8_t output_max, bool rounding) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, size); int16_t chunk_stop = MIN(chunk_start + chunk, size + 1); @@ -164,7 +164,7 @@ void UniformRequantShift_s16_s8(int16_t *data_in, int32_t size, int32_t mul, int8_t output_max, bool rounding) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, size); int16_t chunk_stop = MIN(chunk_start + chunk, size + 1); @@ -229,7 +229,7 @@ void UniformRequantShift_s32_s8(int32_t *data_in, int32_t size, int32_t mul, int8_t output_max, bool rounding) { int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (size >> log2Core) + ((size & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, size); int16_t chunk_stop = MIN(chunk_start + chunk, size + 1); diff --git a/TargetLibraries/PULPOpen/src/Util.c b/TargetLibraries/PULPOpen/src/Util.c index 257ea9590a..3aa62ff899 100644 --- a/TargetLibraries/PULPOpen/src/Util.c +++ b/TargetLibraries/PULPOpen/src/Util.c @@ -27,7 +27,7 @@ * limitations under the License. */ -#include "DeeployMath.h" +#include "DeeployPULPMath.h" #include #include #include diff --git a/TargetLibraries/PULPOpen/src/dory_mem.c b/TargetLibraries/PULPOpen/src/dory_mem.c index 8c04f8f7f8..cfabec271b 100644 --- a/TargetLibraries/PULPOpen/src/dory_mem.c +++ b/TargetLibraries/PULPOpen/src/dory_mem.c @@ -101,44 +101,46 @@ void mem_init() { struct pi_device *get_ram_ptr() { return &ram; } void *ram_malloc(size_t size) { - void *ptr = NULL; + uint32_t ptr; pi_ram_alloc(&ram, &ptr, size); - return ptr; + return (void *)ptr; } -void ram_free(void *ptr, size_t size) { pi_ram_free(&ram, ptr, size); } +void ram_free(void *ptr, size_t size) { + pi_ram_free(&ram, (uint32_t)ptr, size); +} void ram_read(void *dest, void *src, const size_t size) { - pi_ram_read(&ram, src, dest, size); + pi_ram_read(&ram, (uint32_t)src, dest, size); } void ram_write(void *dest, void *src, const size_t size) { - pi_ram_write(&ram, dest, src, size); + pi_ram_write(&ram, (uint32_t)dest, src, size); } void *cl_ram_malloc(size_t size) { - int addr; - pi_cl_ram_req_t req; + uint32_t addr; + pi_cl_ram_alloc_req_t req; pi_cl_ram_alloc(&ram, size, &req); pi_cl_ram_alloc_wait(&req, &addr); return (void *)addr; } void cl_ram_free(void *ptr, size_t size) { - pi_cl_ram_req_t req; - pi_cl_ram_free(&ram, ptr, size, &req); + pi_cl_ram_free_req_t req; + pi_cl_ram_free(&ram, (uint32_t)ptr, size, &req); pi_cl_ram_free_wait(&req); } void cl_ram_read(void *dest, void *src, const size_t size) { pi_cl_ram_req_t req; - pi_cl_ram_read(&ram, src, dest, size, &req); + pi_cl_ram_read(&ram, (uint32_t)src, dest, size, &req); pi_cl_ram_read_wait(&req); } void cl_ram_write(void *dest, void *src, const size_t size) { pi_cl_ram_req_t req; - pi_cl_ram_write(&ram, dest, src, size, &req); + pi_cl_ram_write(&ram, (uint32_t)dest, src, size, &req); pi_cl_ram_write_wait(&req); } @@ -162,7 +164,7 @@ size_t load_file_to_ram(const void *dest, const char *filename) { pi_cl_fs_req_t req; pi_cl_fs_read(fd, buffer, load_size, &req); pi_cl_fs_wait(&req); - cl_ram_write(dest + offset, buffer, load_size); + cl_ram_write((void *)dest + offset, buffer, load_size); offset += load_size; } while (offset < size); diff --git a/TargetLibraries/PULPOpen/src/gemv.c b/TargetLibraries/PULPOpen/src/gemv.c index c774224d6a..c53e4d0b3f 100644 --- a/TargetLibraries/PULPOpen/src/gemv.c +++ b/TargetLibraries/PULPOpen/src/gemv.c @@ -151,5 +151,5 @@ void gemv_s8_s8_plp(int8_t *pIn, int8_t *pBias, int8_t *pOut, int8_t *pWeight, } } } - pi_cl_team_barrier(0); + pi_cl_team_barrier(); } diff --git a/TargetLibraries/PULPOpen/src/iRMSnorm.c b/TargetLibraries/PULPOpen/src/iRMSnorm.c index 78f882e16d..1361cf6e6f 100644 --- a/TargetLibraries/PULPOpen/src/iRMSnorm.c +++ b/TargetLibraries/PULPOpen/src/iRMSnorm.c @@ -67,7 +67,7 @@ void iRMSnorm_s8_s8_plp(int8_t *data_in, int8_t *data_out, int32_t *weight, int32_t intermediate; int8_t core_id = pi_core_id(); - int8_t log2Core = log2(NUM_CORES); + int8_t log2Core = LOG2(NUM_CORES); int16_t chunk = (lastDimLength >> log2Core) + ((lastDimLength & (NUM_CORES - 1)) != 0); int16_t chunk_start = MIN(chunk * core_id, lastDimLength); From 2fa3c319882e2c6fccdd73d4217ac2f72b30b3d3 Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Thu, 18 Sep 2025 16:14:20 +0200 Subject: [PATCH 09/28] Add reuse-tool as an SPDX license header linter (#113) * Use [reuse-tool](https://github.com/fsfe/reuse-tool) for checking license headers Added a wrapper python script to filter the files so we can manually skip what we don't want reuse to check. Otherwise it complains about every single file. * Replace LICENSE file with LICENSES directory and Apache-2.0.txt file Reuse explicitly checks for licenses in the LICENSES directory and doesn't look for it in the LICENSE file. * Add MIT license for the scripts/run_clang_format.py * Add missing license headers * Configure and add CC BY-NC 4.0 license * Update Readme * Call reuse via python if not in PATH * Ignore "TEST_*" directories * Update CONTRIBUTING.md --------- Co-authored-by: Philip Wiese --- .github/PULL_REQUEST_TEMPLATE.md | 6 +- .github/workflows/_runner-chimera.yml | 4 +- .github/workflows/_runner-cortexm.yml | 4 +- .github/workflows/_runner-generic.yml | 4 +- .github/workflows/_runner-mempool.yml | 4 +- ...nner-siracusa-neureka-tiled-sequential.yml | 4 +- .../_runner-siracusa-neureka-tiled.yml | 4 +- .../_runner-siracusa-tiled-sequential.yml | 4 +- .github/workflows/_runner-siracusa-tiled.yml | 4 +- .github/workflows/_runner-siracusa.yml | 4 +- .../_runner-snitch-tiled-sequential.yml | 4 +- .github/workflows/_runner-snitch.yml | 4 +- .github/workflows/_runner-softhier.yml | 4 +- .github/workflows/_select-env.yml | 4 +- .github/workflows/ci-deeploy-testing.yml | 4 +- .github/workflows/ci-deeploy.yml | 4 +- .github/workflows/ci-lint.yml | 55 +---- .github/workflows/ci-platform-chimera.yml | 4 +- .github/workflows/ci-platform-cortexm.yml | 4 +- .github/workflows/ci-platform-generic.yml | 4 +- .github/workflows/ci-platform-mempool.yml | 4 +- .../ci-platform-siracusa-neureka-tiled.yml | 4 +- .../workflows/ci-platform-siracusa-tiled.yml | 4 +- .github/workflows/ci-platform-siracusa.yml | 4 +- .../workflows/ci-platform-snitch-tiled.yml | 4 +- .github/workflows/ci-platform-snitch.yml | 4 +- .github/workflows/ci-platform-softhier.yml | 4 +- .github/workflows/docker-build-deeploy.yml | 4 +- .github/workflows/docker-build-toolchain.yml | 4 +- .github/workflows/infra-generate-ccache.yml | 4 +- .../infra-generate-documentation.yml | 4 +- .gitignore | 4 + .gitmodules | 4 + .isort.cfg | 4 + .pre-commit-config.yaml | 18 +- .style.yapf | 4 + .yamllint | 4 +- .yapfignore | 4 + CHANGELOG.md | 3 + CMakeLists.txt | 4 +- CODEOWNERS | 4 + CONTRIBUTING.md | 21 +- Container/Dockerfile.deeploy | 4 + Container/Dockerfile.toolchain | 4 + Container/Makefile | 24 +-- Deeploy.code-workspace | 4 + Deeploy/AbstractDataTypes.py | 23 +- .../CodeTransformationPasses/Closure.py | 23 +- .../CycleMeasurement.py | 23 +- .../IntrospectiveCodeTransformation.py | 23 +- .../MemoryAllocation.py | 23 +- .../CodeTransformationPasses/PrintInputs.py | 23 +- .../CodeTransformationPasses/__init__.py | 23 +- Deeploy/CommonExtensions/DataTypes.py | 23 +- .../NetworkDeployerWrapper.py | 23 +- .../NetworkDeployers/SignPropDeployer.py | 23 +- .../NetworkDeployers/__init__.py | 23 +- .../AutoTranspose.py | 23 +- .../BindingsOptimization.py | 23 +- .../BindingsOptimizationPasses/PassClasses.py | 23 +- .../BindingsOptimizationPasses/__init__.py | 23 +- .../bindingUtils.py | 23 +- .../OptimizationPasses/Matchers.py | 23 +- .../OptimizationPasses/PassClasses.py | 25 +-- .../TopologyOptimizationPasses/DebugPasses.py | 23 +- .../LoweringOptimizationPasses.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- .../OptimizationPasses/__init__.py | 23 +- .../TypeCheckers/SignPropTypeChecker.py | 23 +- .../CommonExtensions/TypeCheckers/__init__.py | 23 +- Deeploy/CommonExtensions/__init__.py | 23 +- Deeploy/DeeployTypes.py | 25 +-- .../EngineColoringDeployer.py | 23 +- .../NetworkDeployers/__init__.py | 23 +- .../EngineColoringPasses.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- .../OptimizationPasses/__init__.py | 23 +- Deeploy/EngineExtension/__init__.py | 23 +- .../Bindings/AutoFutureBinding.py | 23 +- .../FutureExtension/Bindings/FutureBinding.py | 23 +- Deeploy/FutureExtension/Bindings/__init__.py | 23 +- .../FutureCodeTransformation.py | 23 +- .../CodeTransformationPasses/__init__.py | 23 +- Deeploy/FutureExtension/Future.py | 23 +- Deeploy/FutureExtension/__init__.py | 23 +- Deeploy/MemoryLevelExtension/MemoryLevels.py | 23 +- .../NetworkDeployers/MemoryLevelDeployer.py | 25 +-- .../NetworkDeployers/__init__.py | 23 +- .../MemoryLevelAnnotationPasses.py | 23 +- .../OptimizationPasses/__init__.py | 23 +- Deeploy/MemoryLevelExtension/__init__.py | 23 +- Deeploy/Targets/Chimera/Deployer.py | 23 +- Deeploy/Targets/Chimera/Platform.py | 23 +- .../Chimera/Templates/AllocateTemplate.py | 23 +- Deeploy/Targets/CortexM/Bindings.py | 23 +- Deeploy/Targets/CortexM/DataTypes.py | 23 +- Deeploy/Targets/CortexM/Deployer.py | 23 +- Deeploy/Targets/CortexM/Layers.py | 23 +- Deeploy/Targets/CortexM/Parsers.py | 23 +- Deeploy/Targets/CortexM/Platform.py | 25 +-- .../Targets/CortexM/Templates/AddTemplate.py | 23 +- .../Targets/CortexM/Templates/CLCATemplate.py | 23 +- .../Targets/CortexM/Templates/CMSISUtils.py | 23 +- .../Targets/CortexM/Templates/ConvTemplate.py | 23 +- .../CortexM/Templates/DWConvTemplate.py | 23 +- .../Targets/CortexM/Templates/GEMMTemplate.py | 23 +- .../Templates/LinearAttentionTemplate.py | 23 +- .../Targets/CortexM/Templates/MHSATemplate.py | 23 +- .../CortexM/Templates/MaxPool2DTemplate.py | 23 +- Deeploy/Targets/CortexM/Templates/__init__.py | 23 +- .../TopologyOptimizationPasses/Passes.py | 25 +-- .../TopologyOptimizationPasses/__init__.py | 23 +- Deeploy/Targets/CortexM/TypeCheckers.py | 23 +- Deeploy/Targets/CortexM/__init__.py | 23 +- Deeploy/Targets/Generic/Bindings.py | 26 +-- Deeploy/Targets/Generic/Deployer.py | 23 +- Deeploy/Targets/Generic/Layers.py | 25 +-- Deeploy/Targets/Generic/Parsers.py | 26 +-- Deeploy/Targets/Generic/Platform.py | 26 +-- .../Targets/Generic/Templates/AddTemplate.py | 23 +- .../Generic/Templates/AllocateTemplate.py | 23 +- .../Generic/Templates/ClosureTemplate.py | 23 +- .../Generic/Templates/ConcatTemplate.py | 23 +- .../Targets/Generic/Templates/ConvTemplate.py | 23 +- .../Generic/Templates/DWConvTemplate.py | 23 +- .../Generic/Templates/DebugPrintTemplate.py | 23 +- .../Generic/Templates/DequantTemplate.py | 25 +-- .../Generic/Templates/DummyTemplate.py | 23 +- .../Generic/Templates/FloatAddTemplate.py | 25 +-- .../Generic/Templates/FloatConvTemplate.py | 25 +-- .../Generic/Templates/FloatDWConvTemplate.py | 24 +-- .../Generic/Templates/FloatDivTemplate.py | 23 +- .../Generic/Templates/FloatGELUTemplate.py | 23 +- .../Generic/Templates/FloatGemmTemplate.py | 24 +-- .../Templates/FloatLayernormTemplate.py | 23 +- .../Generic/Templates/FloatMatMulTemplate.py | 24 +-- .../Generic/Templates/FloatMaxPoolTemplate.py | 23 +- .../Generic/Templates/FloatMulTemplate.py | 23 +- .../Generic/Templates/FloatPadTemplate.py | 23 +- .../Templates/FloatReduceMeanTemplate.py | 23 +- .../Templates/FloatReduceSumTemplate.py | 22 +- .../Generic/Templates/FloatReluTemplate.py | 23 +- .../Generic/Templates/FloatSoftmaxTemplate.py | 23 +- .../Targets/Generic/Templates/FreeTemplate.py | 23 +- .../Generic/Templates/GatherTemplate.py | 23 +- .../Targets/Generic/Templates/GemmTemplate.py | 23 +- .../Generic/Templates/ITAMaxTemplate.py | 23 +- .../Templates/ITAPartialMaxTemplate.py | 23 +- .../Generic/Templates/IntegerDivTemplate.py | 23 +- .../Generic/Templates/MatMulTemplate.py | 23 +- .../Generic/Templates/MaxPoolTemplate.py | 23 +- .../Targets/Generic/Templates/MulTemplate.py | 23 +- .../Targets/Generic/Templates/PadTemplate.py | 23 +- .../Generic/Templates/QuantTemplate.py | 23 +- .../Generic/Templates/RQAddTemplate.py | 25 +-- .../Generic/Templates/RQIntegerDivTemplate.py | 23 +- .../Generic/Templates/RQSiGELUTemplate.py | 23 +- .../Templates/RQSiHardswishTemplate.py | 23 +- .../Generic/Templates/ReduceMeanTemplate.py | 23 +- .../Generic/Templates/ReduceSumTemplate.py | 23 +- .../Generic/Templates/RequantShiftTemplate.py | 23 +- .../Generic/Templates/ReshapeTemplate.py | 23 +- .../Targets/Generic/Templates/SkipTemplate.py | 23 +- .../Generic/Templates/SliceTemplate.py | 23 +- .../Generic/Templates/TransposeTemplate.py | 23 +- Deeploy/Targets/Generic/Templates/__init__.py | 23 +- .../Generic/Templates/iGELUTemplate.py | 23 +- .../Generic/Templates/iHardswishTemplate.py | 23 +- .../Generic/Templates/iLayernormTemplate.py | 23 +- .../Generic/Templates/iNoNormTemplate.py | 23 +- .../Generic/Templates/iRMSNormTemplate.py | 23 +- .../iSoftmaxPreAllocatedBuffTemplate.py | 24 +-- .../Generic/Templates/iSoftmaxTemplate.py | 23 +- .../TileConstraints/AddTileConstraint.py | 23 +- .../TileConstraints/BOPTileConstraint.py | 23 +- .../TileConstraints/ConcatTileConstraint.py | 23 +- .../TileConstraints/MulTileConstraint.py | 23 +- .../TileConstraints/NOPTileConstraint.py | 23 +- .../TileConstraints/RQSiGELUTileConstraint.py | 23 +- .../RQSiHardswishTileConstraint.py | 23 +- .../TransposeTileConstraint.py | 23 +- .../TileConstraints/UnaryTileConstraint.py | 23 +- .../TileConstraints/UntiledTileConstraint.py | 23 +- .../Generic/TileConstraints/__init__.py | 23 +- .../iHardswishTileConstraint.py | 23 +- .../TileConstraints/iRMSNormTileConstraint.py | 23 +- Deeploy/Targets/Generic/Tiler.py | 23 +- .../TopologyOptimizationPasses/Passes.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- Deeploy/Targets/Generic/TypeCheckers.py | 25 +-- Deeploy/Targets/Generic/__init__.py | 23 +- Deeploy/Targets/MemPool/Bindings.py | 23 +- Deeploy/Targets/MemPool/DataTypes.py | 23 +- Deeploy/Targets/MemPool/Deployer.py | 23 +- Deeploy/Targets/MemPool/Layers.py | 23 +- Deeploy/Targets/MemPool/Parsers.py | 23 +- Deeploy/Targets/MemPool/Platform.py | 25 +-- .../MemPool/Templates/AllocateTemplate.py | 23 +- .../Targets/MemPool/Templates/ConvTemplate.py | 23 +- .../MemPool/Templates/DWConvTemplate.py | 23 +- .../Targets/MemPool/Templates/FreeTemplate.py | 23 +- .../Targets/MemPool/Templates/GemmTemplate.py | 23 +- .../MemPool/Templates/ITAMaxTemplate.py | 23 +- .../Targets/MemPool/Templates/ITATemplate.py | 23 +- .../Targets/MemPool/Templates/MHSATemplate.py | 23 +- .../MemPool/Templates/MatMulTemplate.py | 23 +- .../MemPool/Templates/MaxPoolTemplate.py | 23 +- .../MemPool/Templates/RQGemmTemplate.py | 23 +- .../MemPool/Templates/RQMatMulTemplate.py | 23 +- .../MemPool/Templates/RequantShiftTemplate.py | 23 +- Deeploy/Targets/MemPool/Templates/__init__.py | 23 +- .../TopologyOptimizationPasses/Passes.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- Deeploy/Targets/MemPool/__init__.py | 23 +- Deeploy/Targets/Neureka/Bindings.py | 25 +-- Deeploy/Targets/Neureka/Deployer.py | 23 +- Deeploy/Targets/Neureka/Engine.py | 23 +- Deeploy/Targets/Neureka/Parsers.py | 23 +- Deeploy/Targets/Neureka/Platform.py | 23 +- .../Neureka/Templates/AllocateTemplate.py | 24 +-- .../Targets/Neureka/Templates/ConvTemplate.py | 23 +- Deeploy/Targets/Neureka/Templates/__init__.py | 23 +- .../TileConstraints/NeurekaDenseConstraint.py | 23 +- .../NeurekaDepthwiseConstraint.py | 23 +- .../NeurekaPointwiseConstraint.py | 23 +- .../Neureka/TileConstraints/__init__.py | 23 +- Deeploy/Targets/Neureka/Tiler.py | 23 +- .../TopologyOptimizationPasses/Passes.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- Deeploy/Targets/Neureka/__init__.py | 23 +- Deeploy/Targets/PULPOpen/Bindings.py | 25 +-- .../AutoTransposeUtils.py | 23 +- .../PULPClusterSynch.py | 23 +- .../PULPClusterTiling.py | 23 +- .../CodeTransformationPasses/PULPL3Tiling.py | 23 +- .../PULPProfileUntiled.py | 23 +- .../CodeTransformationPasses/__init__.py | 23 +- Deeploy/Targets/PULPOpen/DMA/L3Dma.py | 24 +-- Deeploy/Targets/PULPOpen/DMA/MchanDma.py | 24 +-- Deeploy/Targets/PULPOpen/DataTypes.py | 23 +- Deeploy/Targets/PULPOpen/Deployer.py | 23 +- Deeploy/Targets/PULPOpen/Layers.py | 23 +- Deeploy/Targets/PULPOpen/Parsers.py | 23 +- Deeploy/Targets/PULPOpen/Platform.py | 25 +-- .../PULPOpen/Templates/AllocateTemplate.py | 23 +- .../PULPOpen/Templates/ConvTemplate.py | 23 +- .../PULPOpen/Templates/FloatAddTemplate.py | 24 +-- .../PULPOpen/Templates/FloatConvTemplate.py | 23 +- .../PULPOpen/Templates/FloatGELUTemplate.py | 23 +- .../PULPOpen/Templates/FloatGemmTemplate.py | 24 +-- .../Templates/FloatLayernormTemplate.py | 23 +- .../PULPOpen/Templates/FloatMatMulTemplate.py | 24 +-- .../Templates/FloatMaxPoolTemplate.py | 23 +- .../PULPOpen/Templates/FloatMulTemplate.py | 24 +-- .../PULPOpen/Templates/FloatReluTemplate.py | 23 +- .../Templates/FloatSoftmaxTemplate.py | 23 +- .../PULPOpen/Templates/FreeTemplate.py | 23 +- .../PULPOpen/Templates/GEMMTemplate.py | 23 +- .../Templates/MatrixVectorTemplate.py | 23 +- .../PULPOpen/Templates/MaxPool2DTemplate.py | 23 +- .../Targets/PULPOpen/Templates/MulTemplate.py | 23 +- .../PULPOpen/Templates/RQAddTemplate.py | 23 +- .../Templates/RQSiHardswishTemplate.py | 23 +- .../PULPOpen/Templates/ReduceMeanTemplate.py | 23 +- .../Templates/RequantShiftTemplate.py | 23 +- .../Targets/PULPOpen/Templates/SGDTemplate.py | 23 +- .../PULPOpen/Templates/SliceTemplate.py | 23 +- .../SoftmaxCrossEntropyLossTemplate.py | 23 +- .../PULPOpen/Templates/TallGEMMTemplate.py | 23 +- .../PULPOpen/Templates/TransposeTemplate.py | 23 +- .../Templates/UniformRequantShiftTemplate.py | 23 +- .../Targets/PULPOpen/Templates/__init__.py | 23 +- .../PULPOpen/Templates/iRMSNormTemplate.py | 23 +- .../PULPOpen/Templates/iSoftmaxTemplate.py | 23 +- .../TileConstraints/ConvTileConstraint.py | 24 +-- .../TileConstraints/DWConvTileConstraint.py | 24 +-- .../TileConstraints/GEMMTileConstraint.py | 24 +-- .../TileConstraints/GatherTileConstraint.py | 23 +- .../LayernormTileConstraint.py | 24 +-- .../TileConstraints/MatMulTileConstraint.py | 24 +-- .../TileConstraints/MaxPoolTileConstraint.py | 24 +-- .../RequantShiftTileConstraint.py | 23 +- .../TileConstraints/SGDTileConstraint.py | 23 +- .../SoftmaxCrossEntropyTileConstraint.py | 23 +- .../PULPOpen/TileConstraints/__init__.py | 23 +- .../TileConstraints/iSoftmaxTileConstraint.py | 23 +- Deeploy/Targets/PULPOpen/Tiler.py | 24 +-- .../TopologyOptimizationPasses/Passes.py | 23 +- .../TopologyOptimizationPasses/__init__.py | 23 +- Deeploy/Targets/PULPOpen/TypeCheckers.py | 23 +- Deeploy/Targets/PULPOpen/__init__.py | 23 +- Deeploy/Targets/Snitch/Bindings.py | 23 +- .../SnitchClusterSynch.py | 23 +- .../SnitchClusterTiling.py | 23 +- .../SnitchCoreFilter.py | 24 +-- .../SnitchProfileExecutionBlock.py | 23 +- .../CodeTransformationPasses/__init__.py | 23 +- Deeploy/Targets/Snitch/DMA/SnitchDma.py | 24 +-- Deeploy/Targets/Snitch/DataTypes.py | 23 +- Deeploy/Targets/Snitch/Deployer.py | 24 +-- Deeploy/Targets/Snitch/Parsers.py | 25 +-- Deeploy/Targets/Snitch/Platform.py | 24 +-- .../Targets/Snitch/Templates/AddTemplate.py | 23 +- .../Snitch/Templates/AllocateTemplate.py | 24 +-- .../Snitch/Templates/FloatGemmTemplate.py | 23 +- .../Snitch/Templates/FloatSoftmaxTemplate.py | 23 +- .../Targets/Snitch/Templates/FreeTemplate.py | 24 +-- .../Targets/Snitch/Templates/GemmTemplate.py | 23 +- .../Targets/Snitch/Templates/RQAddTemplate.py | 25 +-- .../Snitch/Templates/RqGemmTemplate.py | 23 +- Deeploy/Targets/Snitch/Templates/__init__.py | 23 +- .../Snitch/Templates/iSoftmaxTemplate.py | 23 +- .../TileConstraints/GemmTileConstraint.py | 24 +-- .../TileConstraints/RqGemmTileConstraint.py | 24 +-- .../Snitch/TileConstraints/__init__.py | 23 +- .../TileConstraints/iNoNormTileConstraint.py | 23 +- .../TileConstraints/iSoftmaxTileConstraint.py | 23 +- Deeploy/Targets/Snitch/Tiler.py | 23 +- Deeploy/Targets/Snitch/__init__.py | 23 +- Deeploy/Targets/SoftHier/Deployer.py | 23 +- Deeploy/Targets/SoftHier/Platform.py | 22 +- .../SoftHier/Templates/AllocateTemplate.py | 24 +-- .../SoftHier/Templates/FreeTemplate.py | 24 +-- .../Targets/SoftHier/Templates/__init__.py | 24 +-- Deeploy/Targets/__init__.py | 23 +- Deeploy/TilingExtension/AsyncDma.py | 24 +-- .../DoubleBufferingTilingCodeGeneration.py | 23 +- .../SingleBufferingTilingCodeGeneration.py | 23 +- .../TilingCodeGeneration.py | 23 +- .../TilingHoistingMixIn.py | 24 +-- .../TilingPrototypes.py | 25 +-- .../TilingVariableReplacement.py | 23 +- .../CodeTransformationPasses/__init__.py | 23 +- Deeploy/TilingExtension/GenericFlow.py | 23 +- Deeploy/TilingExtension/HtmlTemplates.py | 23 +- .../TilingExtension/MemoryConstraintFlows.py | 23 +- Deeploy/TilingExtension/MemoryConstraints.py | 23 +- Deeploy/TilingExtension/MemoryScheduler.py | 23 +- Deeploy/TilingExtension/TileConstraint.py | 24 +-- Deeploy/TilingExtension/TilerExtension.py | 24 +-- Deeploy/TilingExtension/TilerModel.py | 24 +-- Deeploy/TilingExtension/TilingCodegen.py | 23 +- Deeploy/TilingExtension/__init__.py | 23 +- Deeploy/__init__.py | 23 +- DeeployTest/CMakeLists.txt | 4 +- DeeployTest/Platforms/Chimera/CMakeLists.txt | 4 +- DeeployTest/Platforms/Chimera/main.c | 6 +- DeeployTest/Platforms/Generic/CMakeLists.txt | 4 +- DeeployTest/Platforms/Generic/main.c | 25 +-- DeeployTest/Platforms/MemPool/CMakeLists.txt | 4 +- DeeployTest/Platforms/MemPool/main.c | 25 +-- DeeployTest/Platforms/PULPOpen/CMakeLists.txt | 4 +- .../Platforms/PULPOpen/inc/CycleCounter.h | 64 ++---- .../Platforms/PULPOpen/src/CycleCounter.c | 58 ++--- .../Platforms/PULPOpen/src/deeploytest.c | 24 +-- DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt | 4 +- .../Platforms/QEMU_ARM/inc/CycleCounter.h | 72 +++---- .../Platforms/QEMU_ARM/src/CycleCounter.c | 108 ++++------ .../Platforms/QEMU_ARM/src/deeploytest.c | 23 +- DeeployTest/Platforms/Siracusa/CMakeLists.txt | 4 +- .../Platforms/Siracusa/inc/CycleCounter.h | 64 ++---- .../Platforms/Siracusa/src/CycleCounter.c | 58 ++--- .../Platforms/Siracusa/src/deeploytest.c | 24 +-- DeeployTest/Platforms/Snitch/CMakeLists.txt | 4 +- DeeployTest/Platforms/Snitch/main.c | 23 +- DeeployTest/Platforms/SoftHier/CMakeLists.txt | 4 +- DeeployTest/Platforms/SoftHier/main.c | 23 +- DeeployTest/deeployStateEqualityTest.py | 24 +-- DeeployTest/generateNetwork.py | 25 +-- DeeployTest/profiling2csv.py | 23 +- DeeployTest/testComponentGraph.py | 24 +-- DeeployTest/testDebugPrintPass.py | 24 +-- DeeployTest/testDmas.py | 24 +-- .../testEngineAwareOptimizerWrapper.py | 24 +-- DeeployTest/testMVP.py | 23 +- DeeployTest/testMemoryLevelExtension.py | 24 +-- .../testPrintInputOutputTransformation.py | 24 +-- DeeployTest/testRegexMatching.py | 24 +-- DeeployTest/testReplaceInsertSubgraph.py | 24 +-- DeeployTest/testRunner_chimera.py | 23 +- DeeployTest/testRunner_cortexm.py | 23 +- DeeployTest/testRunner_generic.py | 23 +- DeeployTest/testRunner_mempool.py | 23 +- DeeployTest/testRunner_siracusa.py | 24 +-- DeeployTest/testRunner_siracusa_l3dma.py | 24 +-- DeeployTest/testRunner_siracusa_mchandma.py | 24 +-- DeeployTest/testRunner_snitch.py | 24 +-- DeeployTest/testRunner_snitch_dma.py | 24 +-- DeeployTest/testRunner_softhier.py | 21 +- DeeployTest/testRunner_tiled_siracusa.py | 23 +- .../testRunner_tiled_siracusa_w_neureka.py | 23 +- DeeployTest/testRunner_tiled_snitch.py | 23 +- DeeployTest/testSchedulingExtension.py | 23 +- DeeployTest/testSlice_PULP.py | 23 +- DeeployTest/testTilerExtension.py | 23 +- DeeployTest/testTypes.py | 23 +- DeeployTest/testUtils/ProfilingTraceParser.py | 23 +- DeeployTest/testUtils/__init__.py | 23 +- DeeployTest/testUtils/codeGenerate.py | 23 +- DeeployTest/testUtils/dmaUtils.py | 24 +-- DeeployTest/testUtils/graphColoring.py | 24 +-- DeeployTest/testUtils/graphDebug.py | 23 +- DeeployTest/testUtils/graphDiffUtils.py | 23 +- DeeployTest/testUtils/platformMapping.py | 23 +- DeeployTest/testUtils/testRunner.py | 23 +- DeeployTest/testUtils/tilingUtils.py | 24 +-- DeeployTest/testUtils/typeMapping.py | 23 +- LICENSE | 201 ------------------ LICENSES/Apache-2.0.txt | 73 +++++++ LICENSES/CC-BY-ND-4.0.txt | 154 ++++++++++++++ LICENSES/MIT.txt | 18 ++ Makefile | 77 +------ README.md | 6 +- REUSE.toml | 36 ++++ TargetLibraries/CMSIS/CMakeLists.txt | 4 +- TargetLibraries/CMSIS/inc/DeeployMath.h | 23 +- TargetLibraries/CMSIS/src/Util.c | 25 +-- TargetLibraries/Chimera/CMakeLists.txt | 4 +- .../Chimera/inc/DeeployChimeraMath.h | 6 +- TargetLibraries/Chimera/src/Add.c | 6 +- TargetLibraries/Generic/CMakeLists.txt | 4 +- .../Generic/inc/DeeployBasicMath.h | 26 +-- .../Generic/inc/kernel/Convolution.h | 26 +-- .../Generic/inc/kernel/DWConvolution.h | 26 +-- TargetLibraries/Generic/inc/kernel/Div.h | 26 +-- TargetLibraries/Generic/inc/kernel/GELU.h | 26 +-- TargetLibraries/Generic/inc/kernel/Gemm.h | 25 +-- .../Generic/inc/kernel/Hardswish.h | 30 +-- .../Generic/inc/kernel/Layernorm.h | 26 +-- TargetLibraries/Generic/inc/kernel/MatMul.h | 26 +-- TargetLibraries/Generic/inc/kernel/MaxPool.h | 25 +-- TargetLibraries/Generic/inc/kernel/RMSNorm.h | 23 +- TargetLibraries/Generic/inc/kernel/RQDiv.h | 26 +-- TargetLibraries/Generic/inc/kernel/RQGELU.h | 26 +-- .../Generic/inc/kernel/RQHardswish.h | 30 +-- TargetLibraries/Generic/inc/kernel/Relu.h | 26 +-- .../Generic/inc/kernel/RequantShift.h | 26 +-- TargetLibraries/Generic/inc/kernel/Softmax.h | 26 +-- TargetLibraries/Generic/inc/macros.h | 27 +-- TargetLibraries/Generic/inc/types.h | 25 +-- TargetLibraries/Generic/inc/utils.h | 25 +-- .../Generic/src/Convolution_fp32.c | 26 +-- TargetLibraries/Generic/src/Convolution_s8.c | 25 +-- .../Generic/src/DWConvolution_fp32.c | 24 +-- .../Generic/src/DWConvolution_s8.c | 25 +-- TargetLibraries/Generic/src/Div_fp32.c | 24 +-- TargetLibraries/Generic/src/Div_s32.c | 25 +-- TargetLibraries/Generic/src/GELU_fp32.c | 24 +-- TargetLibraries/Generic/src/GELU_s8.c | 25 +-- TargetLibraries/Generic/src/Gemm_fp32.c | 26 +-- TargetLibraries/Generic/src/Gemm_s8.c | 24 +-- TargetLibraries/Generic/src/Hardswish_s8.c | 30 +-- TargetLibraries/Generic/src/Layernorm_fp32.c | 24 +-- TargetLibraries/Generic/src/Layernorm_s8.c | 25 +-- TargetLibraries/Generic/src/MatMul_fp32.c | 26 +-- TargetLibraries/Generic/src/MatMul_s8.c | 25 +-- TargetLibraries/Generic/src/MaxPool_fp32.c | 25 +-- TargetLibraries/Generic/src/MaxPool_s8.c | 25 +-- TargetLibraries/Generic/src/RQDiv_s8.c | 24 +-- TargetLibraries/Generic/src/RQGELU_s8.c | 24 +-- TargetLibraries/Generic/src/RQHardswish.c | 30 +-- TargetLibraries/Generic/src/Relu_fp32.c | 23 +- TargetLibraries/Generic/src/RequantShift_s8.c | 26 +-- TargetLibraries/Generic/src/Softmax_fp32.c | 24 +-- TargetLibraries/Generic/src/Softmax_s8.c | 24 +-- TargetLibraries/Generic/src/Util.c | 25 +-- TargetLibraries/Generic/src/iRMSNorm_s8.c | 23 +- TargetLibraries/MemPool/CMakeLists.txt | 4 +- TargetLibraries/MemPool/inc/CycleCounter.h | 79 +++---- TargetLibraries/MemPool/inc/DeeployMath.h | 27 +-- TargetLibraries/MemPool/inc/ITA.h | 25 +-- TargetLibraries/MemPool/inc/constants.h | 27 +-- .../MemPool/inc/kernel/Convolution.h | 26 +-- .../MemPool/inc/kernel/DWConvolution.h | 25 +-- TargetLibraries/MemPool/inc/kernel/Gemm.h | 25 +-- TargetLibraries/MemPool/inc/kernel/MHSA.h | 25 +-- TargetLibraries/MemPool/inc/kernel/MatMul.h | 27 +-- TargetLibraries/MemPool/inc/kernel/MaxPool.h | 25 +-- TargetLibraries/MemPool/inc/kernel/RQGemm.h | 25 +-- TargetLibraries/MemPool/inc/kernel/RQMatMul.h | 25 +-- .../MemPool/inc/kernel/RequantShift.h | 25 +-- TargetLibraries/MemPool/inc/kernel/Softmax.h | 25 +-- TargetLibraries/MemPool/inc/macros.h | 27 +-- TargetLibraries/MemPool/src/Convolution_s8.c | 26 +-- TargetLibraries/MemPool/src/CycleCounter.c | 25 +-- .../MemPool/src/DWConvolution_s8.c | 25 +-- TargetLibraries/MemPool/src/Gemm_s8.c | 25 +-- TargetLibraries/MemPool/src/ITA.c | 25 +-- TargetLibraries/MemPool/src/MHSA_s8.c | 25 +-- TargetLibraries/MemPool/src/MatMul_s16.c | 27 +-- TargetLibraries/MemPool/src/MatMul_s32.c | 27 +-- TargetLibraries/MemPool/src/MatMul_s8.c | 27 +-- TargetLibraries/MemPool/src/MaxPool_s8.c | 25 +-- TargetLibraries/MemPool/src/RQGemm_s8.c | 25 +-- TargetLibraries/MemPool/src/RQMatMul_s8.c | 25 +-- TargetLibraries/MemPool/src/RequantShift_s8.c | 25 +-- TargetLibraries/MemPool/src/Softmax_s8.c | 23 +- TargetLibraries/MemPool/src/Util.c | 25 +-- TargetLibraries/PULPOpen/CMakeLists.txt | 4 +- .../PULPOpen/cmake/pulp-sdk-base.cmake | 4 +- .../PULPOpen/cmake/pulp-sdk-pulp-open.cmake | 4 +- .../PULPOpen/cmake/pulp-sdk-siracusa.cmake | 4 +- .../PULPOpen/inc/DeeployPULPMath.h | 23 +- TargetLibraries/PULPOpen/inc/dory_mem.h | 23 +- TargetLibraries/PULPOpen/inc/kernel/Conv.h | 24 +-- TargetLibraries/PULPOpen/inc/kernel/GELU.h | 24 +-- .../PULPOpen/inc/kernel/Layernorm.h | 23 +- TargetLibraries/PULPOpen/inc/kernel/Matmul.h | 25 +-- TargetLibraries/PULPOpen/inc/kernel/MaxPool.h | 23 +- .../PULPOpen/inc/kernel/RQiHardswish.h | 23 +- TargetLibraries/PULPOpen/inc/kernel/Relu.h | 24 +-- .../PULPOpen/inc/kernel/RequantShift.h | 26 +-- TargetLibraries/PULPOpen/inc/kernel/Softmax.h | 23 +- .../PULPOpen/inc/kernel/UniformRequantShift.h | 30 +-- TargetLibraries/PULPOpen/inc/kernel/gemm.h | 24 +-- TargetLibraries/PULPOpen/inc/kernel/gemv.h | 23 +- .../PULPOpen/inc/kernel/iRMSnorm.h | 23 +- TargetLibraries/PULPOpen/inc/mchan_siracusa.h | 30 +-- TargetLibraries/PULPOpen/inc/mchan_v6.h | 25 +-- TargetLibraries/PULPOpen/inc/mchan_v7.h | 25 +-- TargetLibraries/PULPOpen/inc/pulp_core.h | 31 +-- TargetLibraries/PULPOpen/inc/types.h | 25 +-- .../PULPOpen/src/Convolution_fp32.c | 25 +-- TargetLibraries/PULPOpen/src/GELU.c | 25 +-- TargetLibraries/PULPOpen/src/Gemm.c | 26 +-- TargetLibraries/PULPOpen/src/Layernorm.c | 26 +-- TargetLibraries/PULPOpen/src/Matmul.c | 26 +-- TargetLibraries/PULPOpen/src/MaxPool.c | 25 +-- TargetLibraries/PULPOpen/src/RQiHardswish.c | 23 +- TargetLibraries/PULPOpen/src/Relu.c | 26 +-- TargetLibraries/PULPOpen/src/RequantShift.c | 27 +-- TargetLibraries/PULPOpen/src/Softmax.c | 23 +- .../PULPOpen/src/UniformRequantShift.c | 30 +-- TargetLibraries/PULPOpen/src/Util.c | 25 +-- TargetLibraries/PULPOpen/src/dory_mem.c | 23 +- TargetLibraries/PULPOpen/src/gemv.c | 23 +- TargetLibraries/PULPOpen/src/iRMSnorm.c | 23 +- TargetLibraries/Snitch/CMakeLists.txt | 4 +- TargetLibraries/Snitch/inc/CycleCounter.h | 25 +-- .../Snitch/inc/DeeploySnitchMath.h | 27 +-- TargetLibraries/Snitch/inc/dmaStruct.h | 30 +-- TargetLibraries/Snitch/inc/kernel/Gemm.h | 25 +-- TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h | 30 +-- TargetLibraries/Snitch/inc/kernel/MatMul.h | 27 +-- TargetLibraries/Snitch/inc/kernel/RQGemm.h | 25 +-- TargetLibraries/Snitch/inc/kernel/RQMatMul.h | 25 +-- TargetLibraries/Snitch/inc/kernel/Softmax.h | 30 +-- .../Snitch/inc/kernel/UniformRequantShift.h | 25 +-- TargetLibraries/Snitch/inc/kernel/iNoNorm.h | 30 +-- TargetLibraries/Snitch/inc/kernel/iSoftmax.h | 25 +-- TargetLibraries/Snitch/inc/macros.h | 24 +-- TargetLibraries/Snitch/src/Add.c | 30 +-- TargetLibraries/Snitch/src/CycleCounter.c | 24 +-- TargetLibraries/Snitch/src/Gemm_fp32.c | 30 +-- TargetLibraries/Snitch/src/Gemm_s8.c | 30 +-- TargetLibraries/Snitch/src/MatMul_s16.c | 27 +-- TargetLibraries/Snitch/src/MatMul_s32.c | 27 +-- TargetLibraries/Snitch/src/MatMul_s8.c | 27 +-- TargetLibraries/Snitch/src/RQGemm_s8.c | 25 +-- TargetLibraries/Snitch/src/RQMatMul_s8.c | 25 +-- TargetLibraries/Snitch/src/Softmax_fp32.c | 30 +-- .../Snitch/src/UniformRequantShift.c | 25 +-- TargetLibraries/Snitch/src/Util.c | 25 +-- TargetLibraries/Snitch/src/iNoNorm.c | 30 +-- TargetLibraries/Snitch/src/iSoftmax.c | 25 +-- .../Snitch/src/snitch_nn_add_i8_i8_i8.c | 18 +- TargetLibraries/SoftHier/CMakeLists.txt | 4 +- .../SoftHier/inc/DeeploySoftHierMath.h | 23 +- TargetLibraries/SoftHier/inc/types.h | 25 +-- TargetLibraries/SoftHier/inc/util.h | 25 +-- TargetLibraries/SoftHier/src/Util.c | 25 +-- cmake/Util.cmake | 4 +- cmake/chimera/chimera-sdk.cmake | 4 +- cmake/chimera/toolchain_llvm.cmake | 4 +- cmake/cmsis/cmsis.cmake | 4 +- cmake/cmsis/qemu.cmake | 4 +- cmake/cmsis/toolchain_gcc.cmake | 4 +- cmake/cmsis/toolchain_llvm.cmake | 4 +- cmake/common.cmake | 4 +- cmake/generic/generic.cmake | 4 +- cmake/generic/toolchain_llvm.cmake | 4 +- cmake/mempool/mempool.cmake | 5 +- cmake/mempool/mempool.yaml | 4 +- cmake/mempool/mempool_ita.cmake | 5 +- cmake/mempool/mempool_ita.yaml | 4 +- cmake/mempool/minpool.cmake | 5 +- cmake/mempool/minpool.yaml | 4 +- cmake/mempool/toolchain_gcc.cmake | 4 +- cmake/mempool/toolchain_llvm.cmake | 4 +- cmake/pulp/pulp-open/pulp-open.cmake | 4 +- cmake/pulp/pulp.cmake | 4 +- cmake/pulp/siracusa/siracusa.cmake | 4 +- cmake/pulp/toolchain_gcc.cmake | 4 +- cmake/pulp/toolchain_llvm.cmake | 4 +- cmake/simulation.cmake | 4 +- cmake/snitch/snitch.cmake | 4 +- .../snitch_cluster/snitch_cluster.cmake | 4 +- cmake/snitch/toolchain_llvm.cmake | 4 +- cmake/softhier/softhier_gvsoc.cmake | 4 +- cmake/softhier/toolchain_gcc.cmake | 4 +- docs/Makefile | 6 +- docs/_templates/custom-class-template.rst | 4 + docs/_templates/custom-module-template.rst | 4 + docs/_templates/versions.html | 6 + docs/apidocs.rst | 4 + docs/conf.py | 23 +- docs/index.rst | 4 + docs/make.bat | 4 + docs/tutorials/debugging.rst | 4 + docs/tutorials/overview.rst | 4 + pyproject.toml | 4 + requirements-dev.txt | 5 + scripts/gen_changelog.py | 24 +-- scripts/reuse_skip_wrapper.py | 37 ++++ setup.py | 25 +-- 615 files changed, 1363 insertions(+), 12075 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSES/Apache-2.0.txt create mode 100644 LICENSES/CC-BY-ND-4.0.txt create mode 100644 LICENSES/MIT.txt create mode 100644 REUSE.toml create mode 100755 scripts/reuse_skip_wrapper.py diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fd088f6161..b367d31545 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,13 @@ Describe the intent of your PR here. ## Added -- +- ## Changed -- +- ## Fixed -- +- ## PR Merge Checklist diff --git a/.github/workflows/_runner-chimera.yml b/.github/workflows/_runner-chimera.yml index d9fe7c58f2..fbfe4480f1 100644 --- a/.github/workflows/_runner-chimera.yml +++ b/.github/workflows/_runner-chimera.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-cortexm.yml b/.github/workflows/_runner-cortexm.yml index 995a3abbeb..70ee5b5d45 100644 --- a/.github/workflows/_runner-cortexm.yml +++ b/.github/workflows/_runner-cortexm.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-generic.yml b/.github/workflows/_runner-generic.yml index 7601330743..50fa0f3a3b 100644 --- a/.github/workflows/_runner-generic.yml +++ b/.github/workflows/_runner-generic.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-mempool.yml b/.github/workflows/_runner-mempool.yml index bddf35b024..edd048ba9d 100644 --- a/.github/workflows/_runner-mempool.yml +++ b/.github/workflows/_runner-mempool.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml b/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml index 505fa72f02..b1a8915319 100644 --- a/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml +++ b/.github/workflows/_runner-siracusa-neureka-tiled-sequential.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-siracusa-neureka-tiled.yml b/.github/workflows/_runner-siracusa-neureka-tiled.yml index 1a596a0e91..3e613a84cb 100644 --- a/.github/workflows/_runner-siracusa-neureka-tiled.yml +++ b/.github/workflows/_runner-siracusa-neureka-tiled.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-siracusa-tiled-sequential.yml b/.github/workflows/_runner-siracusa-tiled-sequential.yml index 6f88c624a9..056d8f0398 100644 --- a/.github/workflows/_runner-siracusa-tiled-sequential.yml +++ b/.github/workflows/_runner-siracusa-tiled-sequential.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-siracusa-tiled.yml b/.github/workflows/_runner-siracusa-tiled.yml index c03bf71798..f33836c6b8 100644 --- a/.github/workflows/_runner-siracusa-tiled.yml +++ b/.github/workflows/_runner-siracusa-tiled.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-siracusa.yml b/.github/workflows/_runner-siracusa.yml index 28fa751b72..1972724e9c 100644 --- a/.github/workflows/_runner-siracusa.yml +++ b/.github/workflows/_runner-siracusa.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-snitch-tiled-sequential.yml b/.github/workflows/_runner-snitch-tiled-sequential.yml index 2b9f2d0a27..4128b13186 100644 --- a/.github/workflows/_runner-snitch-tiled-sequential.yml +++ b/.github/workflows/_runner-snitch-tiled-sequential.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-snitch.yml b/.github/workflows/_runner-snitch.yml index 0559b7b6f8..ab0ae55ed7 100644 --- a/.github/workflows/_runner-snitch.yml +++ b/.github/workflows/_runner-snitch.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_runner-softhier.yml b/.github/workflows/_runner-softhier.yml index 445f55114a..e06aea3b9b 100644 --- a/.github/workflows/_runner-softhier.yml +++ b/.github/workflows/_runner-softhier.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/_select-env.yml b/.github/workflows/_select-env.yml index e8a77ee9d8..1085c7eaa1 100644 --- a/.github/workflows/_select-env.yml +++ b/.github/workflows/_select-env.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-deeploy-testing.yml b/.github/workflows/ci-deeploy-testing.yml index 1535951254..a44d557265 100644 --- a/.github/workflows/ci-deeploy-testing.yml +++ b/.github/workflows/ci-deeploy-testing.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-deeploy.yml b/.github/workflows/ci-deeploy.yml index d57c65581f..429e9c2027 100644 --- a/.github/workflows/ci-deeploy.yml +++ b/.github/workflows/ci-deeploy.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml index 3cab31bf3c..75163aafaf 100644 --- a/.github/workflows/ci-lint.yml +++ b/.github/workflows/ci-lint.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- @@ -47,62 +47,21 @@ jobs: - name: Format Python shell: bash run: | - yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . + yapf -rpd -e "*/TEST_*/" -e "*/third_party/" -e "install/" -e "toolchain/" . - name: Format Python Imports shell: bash run: | - isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c + isort --quiet --sg "**/TEST_*/*" --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c autoflake --quiet -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . - name: Format C shell: bash run: | - python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts + python scripts/run_clang_format.py -e "*/TEST_*/*" -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts - name: Format YAML shell: bash run: | yamllint . - - name: Check Python Licenses + - name: Check Licenses shell: bash run: | - missing_py=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.py" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude "run_clang_format.py" . || true) - if [[ -n "$missing_py" ]]; then - echo "Missing SPDX in Python files:"; echo "$missing_py"; exit 1; fi - - name: Check C Licenses - shell: bash - run: | - missing_c=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.c" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true) - if [[ -n "$missing_c" ]]; then - echo "Missing SPDX in C files:"; echo "$missing_c"; exit 1; fi - - name: Check C Header Licenses - shell: bash - run: | - missing_h=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.h" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true) - if [[ -n "$missing_h" ]]; then - echo "Missing SPDX in headers:"; echo "$missing_h"; exit 1; fi - - name: Check YAML Licenses - shell: bash - run: | - missing_yaml=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.yaml" --include="*.yml" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true) - if [[ -n "$missing_yaml" ]]; then - echo "Missing SPDX in YAML files:"; echo "$missing_yaml"; exit 1; fi - - name: Check CMake Licenses - shell: bash - run: | - missing_cmake=$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.cmake" --include="CMakeLists.txt" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true) - if [[ -n "$missing_cmake" ]]; then - echo "Missing SPDX in CMake files:"; echo "$missing_cmake"; exit 1; fi + python scripts/reuse_skip_wrapper.py $(find . \( -name '*.py' -o -name '*.c' -o -name '*.h' -o -name '*.html' -o -name '*.rst' -o -name '*.yml' -o -name '*.yaml' \) -not -path "*toolchain*" -not -path "*third_party*" -not -path "*.git/*" -not -path "*install/*" -type f) diff --git a/.github/workflows/ci-platform-chimera.yml b/.github/workflows/ci-platform-chimera.yml index 6674f40505..79db97abd0 100644 --- a/.github/workflows/ci-platform-chimera.yml +++ b/.github/workflows/ci-platform-chimera.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-cortexm.yml b/.github/workflows/ci-platform-cortexm.yml index d5a2da1dc8..f9020f3646 100644 --- a/.github/workflows/ci-platform-cortexm.yml +++ b/.github/workflows/ci-platform-cortexm.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml index 1e2b13b251..6d690befc1 100644 --- a/.github/workflows/ci-platform-generic.yml +++ b/.github/workflows/ci-platform-generic.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-mempool.yml b/.github/workflows/ci-platform-mempool.yml index f2feed25b3..7f716e2dab 100644 --- a/.github/workflows/ci-platform-mempool.yml +++ b/.github/workflows/ci-platform-mempool.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-siracusa-neureka-tiled.yml b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml index 31f1bcd1e9..e9f920931a 100644 --- a/.github/workflows/ci-platform-siracusa-neureka-tiled.yml +++ b/.github/workflows/ci-platform-siracusa-neureka-tiled.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-siracusa-tiled.yml b/.github/workflows/ci-platform-siracusa-tiled.yml index 0791eab317..dba01455f0 100644 --- a/.github/workflows/ci-platform-siracusa-tiled.yml +++ b/.github/workflows/ci-platform-siracusa-tiled.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml index b1faeb863f..bee1263539 100644 --- a/.github/workflows/ci-platform-siracusa.yml +++ b/.github/workflows/ci-platform-siracusa.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-snitch-tiled.yml b/.github/workflows/ci-platform-snitch-tiled.yml index 75b8b63a54..71d6a93009 100644 --- a/.github/workflows/ci-platform-snitch-tiled.yml +++ b/.github/workflows/ci-platform-snitch-tiled.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-snitch.yml b/.github/workflows/ci-platform-snitch.yml index 73076c66ab..3968ba3201 100644 --- a/.github/workflows/ci-platform-snitch.yml +++ b/.github/workflows/ci-platform-snitch.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/ci-platform-softhier.yml b/.github/workflows/ci-platform-softhier.yml index 6e4921c809..959dca131b 100644 --- a/.github/workflows/ci-platform-softhier.yml +++ b/.github/workflows/ci-platform-softhier.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/docker-build-deeploy.yml b/.github/workflows/docker-build-deeploy.yml index e75d56fb02..9edb90f103 100644 --- a/.github/workflows/docker-build-deeploy.yml +++ b/.github/workflows/docker-build-deeploy.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/docker-build-toolchain.yml b/.github/workflows/docker-build-toolchain.yml index 6509fefa67..d2b8fc7d63 100644 --- a/.github/workflows/docker-build-toolchain.yml +++ b/.github/workflows/docker-build-toolchain.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/infra-generate-ccache.yml b/.github/workflows/infra-generate-ccache.yml index 0428a8333f..721f09870b 100644 --- a/.github/workflows/infra-generate-ccache.yml +++ b/.github/workflows/infra-generate-ccache.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.github/workflows/infra-generate-documentation.yml b/.github/workflows/infra-generate-documentation.yml index 91e02c4b95..8b0ae2b5ce 100644 --- a/.github/workflows/infra-generate-documentation.yml +++ b/.github/workflows/infra-generate-documentation.yml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.gitignore b/.gitignore index d6ecb06744..1115bfa5ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + *~ __pycache__ build diff --git a/.gitmodules b/.gitmodules index def05e2adc..ea01f2734d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + [submodule "pulp-nn-mixed"] path = TargetLibraries/PULPOpen/third_party/pulp-nn-mixed url = https://github.com/pulp-platform/pulp-nn-mixed.git diff --git a/.isort.cfg b/.isort.cfg index 59aa31d957..217d3f7dc1 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + [settings] line_length=120 multi_line_output=2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6525fdda8d..75f2a421bd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 # See https://pre-commit.com for more information @@ -8,12 +8,11 @@ exclude: | (?x)^( .*third_party.* - | .*install.* - | .*toolchain.* + | .*install/.* + | .*toolchain/.* | .*TEST_.* | .*TestFiles.* | .*runtime.* - | .*\.git.* ) repos: @@ -26,12 +25,13 @@ repos: name: Check for trailing whitespace - repo: local hooks: - - id: check-licenses + - id: reuse name: Check SPDX License Headers - entry: bash -c 'make check-licenses' - language: system - pass_filenames: false + entry: scripts/reuse_skip_wrapper.py + language: python stages: [pre-commit, pre-merge-commit, pre-push, manual] + types: [text] + exclude_types: [batch, svg, json, markdown] - repo: https://github.com/google/yapf rev: v0.43.0 hooks: diff --git a/.style.yapf b/.style.yapf index 3389b2a67b..2aa801bde2 100644 --- a/.style.yapf +++ b/.style.yapf @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + [style] based_on_style = google column_limit = 120 diff --git a/.yamllint b/.yamllint index 2b1471b42f..ca8d1f606b 100644 --- a/.yamllint +++ b/.yamllint @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/.yapfignore b/.yapfignore index 200637b4e2..459507ebde 100644 --- a/.yapfignore +++ b/.yapfignore @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + *third_party/ *install/ *toolchain/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cacea0f199..d14570d4b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Add reuse-tool as an SPDX license header linter [#113](https://github.com/pulp-platform/Deeploy/pull/113) - Bug fixes, API Cleanup and Reduce Compiler Warning on PULP [#112](https://github.com/pulp-platform/Deeploy/pull/112) - Fix PULP GEMM `batch` serialization [#109](https://github.com/pulp-platform/Deeploy/pull/109) - Split CI Workflows by Platform and Task, Improve Formatting and Linting Reliability [#108](https://github.com/pulp-platform/Deeploy/pull/108) @@ -37,6 +38,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Extended the pre-commit hooks to remove trailing whitespace, check licenses, format and lint files - Reshape operator support for PULP (`ReshapeTemplate` in bindings) - Missing class attributes in `Closure.py` +- reuse_skip_wrapper.py to manually skip files ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -62,6 +64,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Removed all trailing whitespace - Removed unnecessary includes from the PULP platform header list, such as `DeeployBasicMath.h`, for cleaner code generation - Changed types and added correct casts to fix many compiler warnings in the PULP target library +- Use [reuse-tool](https://github.com/fsfe/reuse-tool) in pre-commit, CI, and Makefile for SPDX license header linting ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a144b04b4..70dec13084 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.12) diff --git a/CODEOWNERS b/CODEOWNERS index 40e51a533d..baeacab34e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1,5 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: CC-BY-ND-4.0 + * @victor-jung @xeratec @lukamac diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 08c2486cd6..2285670366 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,6 @@ # Contribution Guide We encourage submitting your issues and work in pull requests against the `devel` branch. Please understand that we are trying to maintain a consistent minimal quality standard. -Any and all pull requests you submit can only be accepted under the Apache 2.0 License. ## Overview @@ -42,24 +41,16 @@ Additionally, add the title and link to the pull request in the list of pull req Deeploy mainly consists of code implemented in C, Makefile, and Python. To facilitate efficient collaboration among users and contributors, it is important to maintain a consistent coding style. To achieve this, it is strongly recommend to use autoformatting tools with the provided configuration files. Additionally, the Continuous Integration (CI) system checks the adherence to the style guide for each pushed commit. Currently configuration for C using `clang-format` and for Python using `yapf` and `isort` are provided. -To recursively format all Python files run: +You can format all relevant files by running: ```bash -autoflake -i -r --remove-all-unused-imports --ignore-init-module-imports --exclude "*/third_party/**" . -yapf -ipr . -isort . +make format ``` -And for C files: +Alternatively, to only lint the files without modifying them, you can run: ```bash -python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -ir --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format ./ +make lint ``` -Note that third party applications should not be formatted. You can alternatively also run: -```bash -make format -``` -to format all C and Python files. - ### Pre-commit Additionally, we provide the [pre-commit](https://pre-commit.com) configuration file which you can use to install github hooks that execute the formatting commands on your changes. @@ -81,3 +72,7 @@ pre-commit uninstall ``` _Note:_ This configures only the python formatting git hooks. The c formatting is not supported at the moment. + +## Licensing + +Any and all pull requests you submit can only be accepted under the Apache 2.0 License. Every file needs to have an SPDX license header. We use the [reuse-tool](https://github.com/fsfe/reuse-tool) to check for the license header. You can use the same tool to add the license by calling it with the `annotate` command. diff --git a/Container/Dockerfile.deeploy b/Container/Dockerfile.deeploy index 6222492f9c..68f64748cc 100644 --- a/Container/Dockerfile.deeploy +++ b/Container/Dockerfile.deeploy @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + ########## Stage 1: Large image to build toolchains and emulator ########## ARG BASE_IMAGE=ghcr.io/pulp-platform/deeploy-toolchain FROM ${BASE_IMAGE} AS toolchain diff --git a/Container/Dockerfile.toolchain b/Container/Dockerfile.toolchain index 6e15d32197..82669f4116 100644 --- a/Container/Dockerfile.toolchain +++ b/Container/Dockerfile.toolchain @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + ########## Stage 1: Large image to build toolchains and emulator ########## FROM ubuntu:22.04 AS toolchain diff --git a/Container/Makefile b/Container/Makefile index 7432aa059e..cd07d8632b 100644 --- a/Container/Makefile +++ b/Container/Makefile @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: Makefile -# -# Created: 20.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. # Variables TOOLCHAIN_IMAGE ?= ghcr.io/pulp-platform/deeploy-toolchain:latest diff --git a/Deeploy.code-workspace b/Deeploy.code-workspace index 25b484c3fc..e601282bd3 100644 --- a/Deeploy.code-workspace +++ b/Deeploy.code-workspace @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + { "folders": [ { diff --git a/Deeploy/AbstractDataTypes.py b/Deeploy/AbstractDataTypes.py index 7c3601c0e6..b3b0128621 100644 --- a/Deeploy/AbstractDataTypes.py +++ b/Deeploy/AbstractDataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AbstractDataTypes.py -# -# Last edited: 25.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py index e256a7709e..c5f9c883af 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Closure.py -# -# Last edited: 12.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Optional, Tuple, Type, Union diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/CycleMeasurement.py b/Deeploy/CommonExtensions/CodeTransformationPasses/CycleMeasurement.py index eb74e5a70f..42f5d57b1a 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/CycleMeasurement.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/CycleMeasurement.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: CycleMeasurement.py -# -# Last edited: 13.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py index fbb1d0b135..99b8eb132b 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/IntrospectiveCodeTransformation.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: IntrospectiveBinding.py -# -# Last edited: 10.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import types from typing import Dict, List diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py index 004565760f..ff0aceea2e 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryAllocation.py -# -# Last edited: 12.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re from functools import partial diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py index 5c2d212c07..300c5d2ad9 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/PrintInputs.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PrintInput.py -# -# Last edited: 13.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re from typing import Optional, Tuple diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/__init__.py b/Deeploy/CommonExtensions/CodeTransformationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/__init__.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/DataTypes.py b/Deeploy/CommonExtensions/DataTypes.py index 050e5b44ff..4f6dba3827 100644 --- a/Deeploy/CommonExtensions/DataTypes.py +++ b/Deeploy/CommonExtensions/DataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: BasicDataTypes.py -# -# Last edited: 31.08.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Iterable, Tuple, Type, Union diff --git a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py index 6a99627a1b..4b9568bdde 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: NetworkDeployerWrapper.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Any, Tuple, Union diff --git a/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py b/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py index c7174e175c..fc9adf96be 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SignPropDeployer.py -# -# Last edited: 11.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/CommonExtensions/NetworkDeployers/__init__.py b/Deeploy/CommonExtensions/NetworkDeployers/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/__init__.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/AutoTranspose.py b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/AutoTranspose.py index 5ff95db746..8a7191ad2a 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/AutoTranspose.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/AutoTranspose.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AutoTranspose.py -# -# Last edited: 20.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import onnx_graphsurgeon as gs diff --git a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/BindingsOptimization.py b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/BindingsOptimization.py index df97a96c5c..8740b8d296 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/BindingsOptimization.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/BindingsOptimization.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: BindingsOptimization.py -# -# Last edited: 21.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/PassClasses.py b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/PassClasses.py index 475809ba80..738b6d60f5 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/PassClasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/PassClasses.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PassClasses.py -# -# Last edited: 21.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import onnx_graphsurgeon as gs diff --git a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/__init__.py b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/__init__.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/bindingUtils.py b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/bindingUtils.py index 01958ccad2..4737a6bd5d 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/bindingUtils.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/BindingsOptimizationPasses/bindingUtils.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: bindingUtils.py -# -# Last edited: 21.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import Any, Dict, List, Tuple, Union diff --git a/Deeploy/CommonExtensions/OptimizationPasses/Matchers.py b/Deeploy/CommonExtensions/OptimizationPasses/Matchers.py index 54ec01fbaf..cec95ec134 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/Matchers.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/Matchers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Matchers.py -# -# Last edited: 28.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re from typing import Dict, Literal, NamedTuple, Optional diff --git a/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py b/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py index e027e1dafa..dfca7743f2 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: PassClasses.py -# -# Last edited: 28.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: -# Moritz Scherer, ETH Zurich -# Georg Rutishauser, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Optional diff --git a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/DebugPasses.py b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/DebugPasses.py index 7525bbbaa9..bd632cefdd 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/DebugPasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/DebugPasses.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: DebugPasses.py -# -# Last edited: 28.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from functools import partial diff --git a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py index 4e95f9855b..7ef9e96ef0 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: LoweringOptimizationPasses.py -# -# Last edited: 07.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from functools import partial from typing import Iterable, List, Optional, Sequence, Tuple, TypeVar, Union diff --git a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/__init__.py b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/__init__.py index 898895b895..d6474eb128 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 28.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/OptimizationPasses/__init__.py b/Deeploy/CommonExtensions/OptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/__init__.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py b/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py index bdcb6ea5f9..bb34147d23 100644 --- a/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py +++ b/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SignPropChecker.py -# -# Last edited: 19.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Optional diff --git a/Deeploy/CommonExtensions/TypeCheckers/__init__.py b/Deeploy/CommonExtensions/TypeCheckers/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/TypeCheckers/__init__.py +++ b/Deeploy/CommonExtensions/TypeCheckers/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/CommonExtensions/__init__.py b/Deeploy/CommonExtensions/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/CommonExtensions/__init__.py +++ b/Deeploy/CommonExtensions/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index 125d2a8ee8..b638cbd594 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: DeeployTypes.py -# -# Last edited: 17.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py index dfadf558b4..4b05ab5be4 100644 --- a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py +++ b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: EngineColoringDeployer.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Any, Callable, Dict, Type, Union diff --git a/Deeploy/EngineExtension/NetworkDeployers/__init__.py b/Deeploy/EngineExtension/NetworkDeployers/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/EngineExtension/NetworkDeployers/__init__.py +++ b/Deeploy/EngineExtension/NetworkDeployers/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/EngineColoringPasses.py b/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/EngineColoringPasses.py index 4c3bc1f164..82b7d1fde4 100644 --- a/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/EngineColoringPasses.py +++ b/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/EngineColoringPasses.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: EngineColoringPasses.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Optional, Tuple diff --git a/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/__init__.py b/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/EngineExtension/OptimizationPasses/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/EngineExtension/OptimizationPasses/__init__.py b/Deeploy/EngineExtension/OptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/EngineExtension/OptimizationPasses/__init__.py +++ b/Deeploy/EngineExtension/OptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/EngineExtension/__init__.py b/Deeploy/EngineExtension/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/EngineExtension/__init__.py +++ b/Deeploy/EngineExtension/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py b/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py index 6e9d295b0a..a32875bc72 100644 --- a/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py +++ b/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPDMAFutureBinding.py -# -# Last edited: 08.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Optional diff --git a/Deeploy/FutureExtension/Bindings/FutureBinding.py b/Deeploy/FutureExtension/Bindings/FutureBinding.py index 1a8b2214a2..ce1d927fe2 100644 --- a/Deeploy/FutureExtension/Bindings/FutureBinding.py +++ b/Deeploy/FutureExtension/Bindings/FutureBinding.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: DMABinding.py -# -# Last edited: 08.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Optional diff --git a/Deeploy/FutureExtension/Bindings/__init__.py b/Deeploy/FutureExtension/Bindings/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/FutureExtension/Bindings/__init__.py +++ b/Deeploy/FutureExtension/Bindings/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/FutureExtension/CodeTransformationPasses/FutureCodeTransformation.py b/Deeploy/FutureExtension/CodeTransformationPasses/FutureCodeTransformation.py index 0bce6bcdd1..19b4b7d422 100644 --- a/Deeploy/FutureExtension/CodeTransformationPasses/FutureCodeTransformation.py +++ b/Deeploy/FutureExtension/CodeTransformationPasses/FutureCodeTransformation.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Future.py -# -# Last edited: 12.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Tuple diff --git a/Deeploy/FutureExtension/CodeTransformationPasses/__init__.py b/Deeploy/FutureExtension/CodeTransformationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/FutureExtension/CodeTransformationPasses/__init__.py +++ b/Deeploy/FutureExtension/CodeTransformationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/FutureExtension/Future.py b/Deeploy/FutureExtension/Future.py index 7e4969de42..eff83a917c 100644 --- a/Deeploy/FutureExtension/Future.py +++ b/Deeploy/FutureExtension/Future.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Future.py -# -# Last edited: 07.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Optional, Type diff --git a/Deeploy/FutureExtension/__init__.py b/Deeploy/FutureExtension/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/FutureExtension/__init__.py +++ b/Deeploy/FutureExtension/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/MemoryLevelExtension/MemoryLevels.py b/Deeploy/MemoryLevelExtension/MemoryLevels.py index 06b9d4725f..53f236c43f 100644 --- a/Deeploy/MemoryLevelExtension/MemoryLevels.py +++ b/Deeploy/MemoryLevelExtension/MemoryLevels.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryLevel.py -# -# Last edited: 04.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Optional, Sequence, Tuple diff --git a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py index 3d1e12f68f..9baeff2396 100644 --- a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py +++ b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryLevelAnnotation.py -# -# Last edited: 04.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# Moritz Scherer, ETH Zurich -# Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from types import MappingProxyType from typing import Any, Callable, Dict, List, Tuple, Type, Union diff --git a/Deeploy/MemoryLevelExtension/NetworkDeployers/__init__.py b/Deeploy/MemoryLevelExtension/NetworkDeployers/__init__.py index 65ec809815..be436b64a3 100644 --- a/Deeploy/MemoryLevelExtension/NetworkDeployers/__init__.py +++ b/Deeploy/MemoryLevelExtension/NetworkDeployers/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/MemoryLevelExtension/OptimizationPasses/MemoryLevelAnnotationPasses.py b/Deeploy/MemoryLevelExtension/OptimizationPasses/MemoryLevelAnnotationPasses.py index 3069262b26..775f5cbfc5 100644 --- a/Deeploy/MemoryLevelExtension/OptimizationPasses/MemoryLevelAnnotationPasses.py +++ b/Deeploy/MemoryLevelExtension/OptimizationPasses/MemoryLevelAnnotationPasses.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryLevelAnnotationPasses.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Tuple diff --git a/Deeploy/MemoryLevelExtension/OptimizationPasses/__init__.py b/Deeploy/MemoryLevelExtension/OptimizationPasses/__init__.py index 65ec809815..be436b64a3 100644 --- a/Deeploy/MemoryLevelExtension/OptimizationPasses/__init__.py +++ b/Deeploy/MemoryLevelExtension/OptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/MemoryLevelExtension/__init__.py b/Deeploy/MemoryLevelExtension/__init__.py index 65ec809815..be436b64a3 100644 --- a/Deeploy/MemoryLevelExtension/__init__.py +++ b/Deeploy/MemoryLevelExtension/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Chimera/Deployer.py b/Deeploy/Targets/Chimera/Deployer.py index 8f45d636ef..ba28279b66 100644 --- a/Deeploy/Targets/Chimera/Deployer.py +++ b/Deeploy/Targets/Chimera/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Deployer.py -# -# Last edited: 16.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/Chimera/Platform.py b/Deeploy/Targets/Chimera/Platform.py index 8c98a649cc..0244502fd2 100644 --- a/Deeploy/Targets/Chimera/Platform.py +++ b/Deeploy/Targets/Chimera/Platform.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: Platform.py -# -# Last edited: 16.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List diff --git a/Deeploy/Targets/Chimera/Templates/AllocateTemplate.py b/Deeploy/Targets/Chimera/Templates/AllocateTemplate.py index dc2c774a2b..60a095bc47 100644 --- a/Deeploy/Targets/Chimera/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/Chimera/Templates/AllocateTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 16.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/CortexM/Bindings.py b/Deeploy/Targets/CortexM/Bindings.py index 3b7b7ff11d..bfe7b05afc 100644 --- a/Deeploy/Targets/CortexM/Bindings.py +++ b/Deeploy/Targets/CortexM/Bindings.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: CMSISBindings.py -# -# Last edited: 17.12.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ diff --git a/Deeploy/Targets/CortexM/DataTypes.py b/Deeploy/Targets/CortexM/DataTypes.py index 9951cb357b..66f031d3cd 100644 --- a/Deeploy/Targets/CortexM/DataTypes.py +++ b/Deeploy/Targets/CortexM/DataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: CMSISDataTypes.py -# -# Last edited: 01.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.AbstractDataTypes import PointerClass, Struct, VoidType from Deeploy.CommonExtensions.DataTypes import int32_t diff --git a/Deeploy/Targets/CortexM/Deployer.py b/Deeploy/Targets/CortexM/Deployer.py index 55f8987304..bef8fdcf36 100644 --- a/Deeploy/Targets/CortexM/Deployer.py +++ b/Deeploy/Targets/CortexM/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: NetworkDeployer.py -# -# Last edited: 26.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/CortexM/Layers.py b/Deeploy/Targets/CortexM/Layers.py index ba60a2e214..e64fe6a6ca 100644 --- a/Deeploy/Targets/CortexM/Layers.py +++ b/Deeploy/Targets/CortexM/Layers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: CMSISLayers.py -# -# Last edited: 22.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Tuple diff --git a/Deeploy/Targets/CortexM/Parsers.py b/Deeploy/Targets/CortexM/Parsers.py index e81caf0077..0fc1efef9e 100644 --- a/Deeploy/Targets/CortexM/Parsers.py +++ b/Deeploy/Targets/CortexM/Parsers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: CMSISParsers.py -# -# Last edited: 17.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Tuple diff --git a/Deeploy/Targets/CortexM/Platform.py b/Deeploy/Targets/CortexM/Platform.py index c65bb86766..f788baaf18 100644 --- a/Deeploy/Targets/CortexM/Platform.py +++ b/Deeploy/Targets/CortexM/Platform.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: CMSISPlatform.py -# -# Last edited: 17.12.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import ConstantBuffer, DeploymentEngine, DeploymentPlatform, NodeMapper, NodeTemplate, \ StructBuffer, TopologyOptimizer, TransientBuffer, VariableBuffer diff --git a/Deeploy/Targets/CortexM/Templates/AddTemplate.py b/Deeploy/Targets/CortexM/Templates/AddTemplate.py index b477193b9f..664bb2e65c 100644 --- a/Deeploy/Targets/CortexM/Templates/AddTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/AddTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: AddTemplate.py -# -# Last edited: 18.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/CortexM/Templates/CLCATemplate.py b/Deeploy/Targets/CortexM/Templates/CLCATemplate.py index 3eeb3556ce..470621dd33 100644 --- a/Deeploy/Targets/CortexM/Templates/CLCATemplate.py +++ b/Deeploy/Targets/CortexM/Templates/CLCATemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: CLCATemplate.py -# -# Last edited: 26.08.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/CMSISUtils.py b/Deeploy/Targets/CortexM/Templates/CMSISUtils.py index 3d0cbbc311..ea8abbbc74 100644 --- a/Deeploy/Targets/CortexM/Templates/CMSISUtils.py +++ b/Deeploy/Targets/CortexM/Templates/CMSISUtils.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: CMSISUtils.py -# -# Last edited: 10.01.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import numpy as np diff --git a/Deeploy/Targets/CortexM/Templates/ConvTemplate.py b/Deeploy/Targets/CortexM/Templates/ConvTemplate.py index 5743fc9845..d5e05c8343 100644 --- a/Deeploy/Targets/CortexM/Templates/ConvTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/ConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: ConvTemplate.py -# -# Last edited: 17.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/CortexM/Templates/DWConvTemplate.py b/Deeploy/Targets/CortexM/Templates/DWConvTemplate.py index 056ef4d059..3733cfc4c6 100644 --- a/Deeploy/Targets/CortexM/Templates/DWConvTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/DWConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: DWConvTemplate.py -# -# Last edited: 04.01.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/GEMMTemplate.py b/Deeploy/Targets/CortexM/Templates/GEMMTemplate.py index 237f5eec7c..d82704cdcf 100644 --- a/Deeploy/Targets/CortexM/Templates/GEMMTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/GEMMTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: GEMMTemplate.py -# -# Last edited: 20.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/LinearAttentionTemplate.py b/Deeploy/Targets/CortexM/Templates/LinearAttentionTemplate.py index 97fd3b6efd..2220d2974a 100644 --- a/Deeploy/Targets/CortexM/Templates/LinearAttentionTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/LinearAttentionTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: LinearAttentionTemplate.py -# -# Last edited: 05.06.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/MHSATemplate.py b/Deeploy/Targets/CortexM/Templates/MHSATemplate.py index 0ae237ccef..158ef9c97c 100644 --- a/Deeploy/Targets/CortexM/Templates/MHSATemplate.py +++ b/Deeploy/Targets/CortexM/Templates/MHSATemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MHSATemplate.py -# -# Last edited: 01.01.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/MaxPool2DTemplate.py b/Deeploy/Targets/CortexM/Templates/MaxPool2DTemplate.py index 37143747ec..415a098d01 100644 --- a/Deeploy/Targets/CortexM/Templates/MaxPool2DTemplate.py +++ b/Deeploy/Targets/CortexM/Templates/MaxPool2DTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: MaxPool2DTemplate.py -# -# Last edited: 27.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/CortexM/Templates/__init__.py b/Deeploy/Targets/CortexM/Templates/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/CortexM/Templates/__init__.py +++ b/Deeploy/Targets/CortexM/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/CortexM/TopologyOptimizationPasses/Passes.py b/Deeploy/Targets/CortexM/TopologyOptimizationPasses/Passes.py index dcc169ee45..7f9b7ef079 100644 --- a/Deeploy/Targets/CortexM/TopologyOptimizationPasses/Passes.py +++ b/Deeploy/Targets/CortexM/TopologyOptimizationPasses/Passes.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: CMSISPasses.py -# -# Last edited: 17.12.2022 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Georg Rutishauser, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import numpy as np import onnx_graphsurgeon as gs diff --git a/Deeploy/Targets/CortexM/TopologyOptimizationPasses/__init__.py b/Deeploy/Targets/CortexM/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/CortexM/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/Targets/CortexM/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/CortexM/TypeCheckers.py b/Deeploy/Targets/CortexM/TypeCheckers.py index c5f58a9f47..b58ab91ddd 100644 --- a/Deeploy/Targets/CortexM/TypeCheckers.py +++ b/Deeploy/Targets/CortexM/TypeCheckers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: CMSISCheckers.py -# -# Last edited: 18.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Sequence, Type diff --git a/Deeploy/Targets/CortexM/__init__.py b/Deeploy/Targets/CortexM/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/CortexM/__init__.py +++ b/Deeploy/Targets/CortexM/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Generic/Bindings.py b/Deeploy/Targets/Generic/Bindings.py index ec9c32a6d2..24fc8c0d21 100644 --- a/Deeploy/Targets/Generic/Bindings.py +++ b/Deeploy/Targets/Generic/Bindings.py @@ -1,30 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: BasicBindings.py -# -# Last edited: 05.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Philip Wiese, ETH Zurich -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import itertools diff --git a/Deeploy/Targets/Generic/Deployer.py b/Deeploy/Targets/Generic/Deployer.py index 8dc216d7e7..3cef57a2ea 100644 --- a/Deeploy/Targets/Generic/Deployer.py +++ b/Deeploy/Targets/Generic/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GenericDeployer.py -# -# Last edited: 04.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/Generic/Layers.py b/Deeploy/Targets/Generic/Layers.py index 17e4e6ea42..e01f5e79d0 100644 --- a/Deeploy/Targets/Generic/Layers.py +++ b/Deeploy/Targets/Generic/Layers.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: BasicLayers.py -# -# Last edited: 17.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import List, Tuple diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index 148d1b0e32..39372c5144 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -1,30 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: BasicParsers.py -# -# Last edited: 12.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Tuple diff --git a/Deeploy/Targets/Generic/Platform.py b/Deeploy/Targets/Generic/Platform.py index 7a62a10346..0a620f9eb2 100644 --- a/Deeploy/Targets/Generic/Platform.py +++ b/Deeploy/Targets/Generic/Platform.py @@ -1,30 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: GenericPlatform.py -# -# Last edited: 05.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Philip Wiese, ETH Zurich -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ RemoveEmptyConvBiasPass diff --git a/Deeploy/Targets/Generic/Templates/AddTemplate.py b/Deeploy/Targets/Generic/Templates/AddTemplate.py index 4eec289669..75c16ac429 100644 --- a/Deeploy/Targets/Generic/Templates/AddTemplate.py +++ b/Deeploy/Targets/Generic/Templates/AddTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: AddTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/AllocateTemplate.py b/Deeploy/Targets/Generic/Templates/AllocateTemplate.py index b3638bcee6..9d004c059d 100644 --- a/Deeploy/Targets/Generic/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/Generic/Templates/AllocateTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/ClosureTemplate.py b/Deeploy/Targets/Generic/Templates/ClosureTemplate.py index 4398f635e6..50f667e7c7 100644 --- a/Deeploy/Targets/Generic/Templates/ClosureTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ClosureTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ClosureTemplate.py -# -# Last edited: 15.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate, OperatorRepresentation diff --git a/Deeploy/Targets/Generic/Templates/ConcatTemplate.py b/Deeploy/Targets/Generic/Templates/ConcatTemplate.py index e233e93726..17a66b91d3 100644 --- a/Deeploy/Targets/Generic/Templates/ConcatTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ConcatTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ConcatTemplate.py -# -# Last edited: 19.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ConvTemplate.py b/Deeploy/Targets/Generic/Templates/ConvTemplate.py index c65f7ee259..51f292dcae 100644 --- a/Deeploy/Targets/Generic/Templates/ConvTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ConvTemplate.py -# -# Last edited: 04.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/DWConvTemplate.py b/Deeploy/Targets/Generic/Templates/DWConvTemplate.py index e4c8513931..aeeb1ac523 100644 --- a/Deeploy/Targets/Generic/Templates/DWConvTemplate.py +++ b/Deeploy/Targets/Generic/Templates/DWConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: DWConvTemplate.py -# -# Last edited: 05.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py b/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py index abb508cb61..d67af90b40 100644 --- a/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py +++ b/Deeploy/Targets/Generic/Templates/DebugPrintTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: DebugPrintTemplate.py -# -# Last edited: 14.12.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/DequantTemplate.py b/Deeploy/Targets/Generic/Templates/DequantTemplate.py index 99eeecf3eb..80f34fa66c 100644 --- a/Deeploy/Targets/Generic/Templates/DequantTemplate.py +++ b/Deeploy/Targets/Generic/Templates/DequantTemplate.py @@ -1,28 +1,7 @@ -# ---------------------------------------------------------------------- - -# File: DequantTemplate.py - -# Last edited: 17.03.2025 - -# Copyright (C) 2025, ETH Zurich and University of Bologna. - -# Author: Federico Brancasi, ETH Zurich - -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/DummyTemplate.py b/Deeploy/Targets/Generic/Templates/DummyTemplate.py index 6ae2d03a77..b5123f9db1 100644 --- a/Deeploy/Targets/Generic/Templates/DummyTemplate.py +++ b/Deeploy/Targets/Generic/Templates/DummyTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: DummyTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatAddTemplate.py b/Deeploy/Targets/Generic/Templates/FloatAddTemplate.py index 51ff681cb6..ec680e1a6b 100644 --- a/Deeploy/Targets/Generic/Templates/FloatAddTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatAddTemplate.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatAddTemplate.py -# -# Last edited: 13.11.2024 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Authors: -# - Francesco Conti, UNIBO -# - Alberto Dequino, UNIBO -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py b/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py index faaead90ce..f1cb7f15ab 100644 --- a/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FLoatConvTemplate.py -# -# Last edited: 12.05.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Authors: -# - Run Wang, ETH Zurich -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatDWConvTemplate.py b/Deeploy/Targets/Generic/Templates/FloatDWConvTemplate.py index 80ae4cb482..0e0fee7a86 100644 --- a/Deeploy/Targets/Generic/Templates/FloatDWConvTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatDWConvTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: FLoatDWConvTemplate.py -# -# Last edited: 12.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatDivTemplate.py b/Deeploy/Targets/Generic/Templates/FloatDivTemplate.py index be713b3fda..34236311a0 100644 --- a/Deeploy/Targets/Generic/Templates/FloatDivTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatDivTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatDivTemplate.py -# -# Last edited: 23.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatGELUTemplate.py b/Deeploy/Targets/Generic/Templates/FloatGELUTemplate.py index 7b011d76d5..fb74d01258 100644 --- a/Deeploy/Targets/Generic/Templates/FloatGELUTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatGELUTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatGELUTemplate.py -# -# Last edited: 28.03.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py b/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py index 5d05ee0089..69bea8484e 100644 --- a/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatGemmTemplate.py @@ -1,27 +1,7 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GemmTemplate.py.py -# -# Last edited: 27.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the Licens + from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" diff --git a/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py b/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py index 6e7758347c..cfb35b60c6 100644 --- a/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatLayernormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatConvTemplate.py -# -# Last edited: 23.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatMatMulTemplate.py b/Deeploy/Targets/Generic/Templates/FloatMatMulTemplate.py index 1d6121b131..d8a9f5b4b2 100644 --- a/Deeploy/Targets/Generic/Templates/FloatMatMulTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatMatMulTemplate.py @@ -1,27 +1,7 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MatMul.py.py -# -# Last edited: 27.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the Licens + from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" diff --git a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py index eddde93446..b5401d174f 100644 --- a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MaxPoolTemplate.py -# -# Last edited: 24.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatMulTemplate.py b/Deeploy/Targets/Generic/Templates/FloatMulTemplate.py index 908c26ef59..3c8c2da501 100644 --- a/Deeploy/Targets/Generic/Templates/FloatMulTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatMulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MulTemplate.py -# -# Last edited: 02.09.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py index c7a6d6c714..c1bd567641 100644 --- a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: PadTemplate.py -# -# Last edited: 27.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatReduceMeanTemplate.py b/Deeploy/Targets/Generic/Templates/FloatReduceMeanTemplate.py index 719a06be6f..005b0b8893 100644 --- a/Deeploy/Targets/Generic/Templates/FloatReduceMeanTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatReduceMeanTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ReduceMeanTemplate.py -# -# Last edited: 04.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py b/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py index c797d406e6..e9a9ff1742 100644 --- a/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatReduceSumTemplate.py @@ -1,26 +1,6 @@ -# ---------------------------------------------------------------------- # -# File: ReduceSumTemplateFloat.py +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# Last edited: March 14, 2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# Modified for float support -# ---------------------------------------------------------------------- # # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatReluTemplate.py b/Deeploy/Targets/Generic/Templates/FloatReluTemplate.py index 7bb71487ee..c40d888d06 100644 --- a/Deeploy/Targets/Generic/Templates/FloatReluTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatReluTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatReluTemplate.py -# -# Last edited: 23.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FloatSoftmaxTemplate.py b/Deeploy/Targets/Generic/Templates/FloatSoftmaxTemplate.py index d0784f1378..118543c0b0 100644 --- a/Deeploy/Targets/Generic/Templates/FloatSoftmaxTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatSoftmaxTemplate.py -# -# Last edited: 23.1.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/FreeTemplate.py b/Deeploy/Targets/Generic/Templates/FreeTemplate.py index 84e13d0583..4e8b74bc8c 100644 --- a/Deeploy/Targets/Generic/Templates/FreeTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FreeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FreeTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/GatherTemplate.py b/Deeploy/Targets/Generic/Templates/GatherTemplate.py index 918125606f..dd5e534fa4 100644 --- a/Deeploy/Targets/Generic/Templates/GatherTemplate.py +++ b/Deeploy/Targets/Generic/Templates/GatherTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: GatherTemplate.py -# -# Last edited: 16.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/GemmTemplate.py b/Deeploy/Targets/Generic/Templates/GemmTemplate.py index 5bc780d223..62d760d15c 100644 --- a/Deeploy/Targets/Generic/Templates/GemmTemplate.py +++ b/Deeploy/Targets/Generic/Templates/GemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GemmTemplate.py.py -# -# Last edited: 05.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py b/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py index a8269d2eb2..c943f5cf2c 100644 --- a/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ITAMaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ITAMaxTemplate.py -# -# Last edited: 27.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ITAPartialMaxTemplate.py b/Deeploy/Targets/Generic/Templates/ITAPartialMaxTemplate.py index f813dca776..c5b3675acd 100644 --- a/Deeploy/Targets/Generic/Templates/ITAPartialMaxTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ITAPartialMaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ITAPartialMaxTemplate.py -# -# Last edited: 08.01.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/Generic/Templates/IntegerDivTemplate.py b/Deeploy/Targets/Generic/Templates/IntegerDivTemplate.py index 6946b60214..d6495a152a 100644 --- a/Deeploy/Targets/Generic/Templates/IntegerDivTemplate.py +++ b/Deeploy/Targets/Generic/Templates/IntegerDivTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: IntegerDivTemplate.py -# -# Last edited: 02.09.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/MatMulTemplate.py b/Deeploy/Targets/Generic/Templates/MatMulTemplate.py index 038be0c634..d1b25c1b0d 100644 --- a/Deeploy/Targets/Generic/Templates/MatMulTemplate.py +++ b/Deeploy/Targets/Generic/Templates/MatMulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MatMulTemplate.py -# -# Last edited: 02.09.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/MaxPoolTemplate.py b/Deeploy/Targets/Generic/Templates/MaxPoolTemplate.py index c66358e45d..1a1b3060bc 100644 --- a/Deeploy/Targets/Generic/Templates/MaxPoolTemplate.py +++ b/Deeploy/Targets/Generic/Templates/MaxPoolTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MaxPoolTemplate.py -# -# Last edited: 04.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/MulTemplate.py b/Deeploy/Targets/Generic/Templates/MulTemplate.py index f96b549090..5709eef4bf 100644 --- a/Deeploy/Targets/Generic/Templates/MulTemplate.py +++ b/Deeploy/Targets/Generic/Templates/MulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MulTemplate.py -# -# Last edited: 02.09.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/PadTemplate.py b/Deeploy/Targets/Generic/Templates/PadTemplate.py index dfcced9249..f0d4462648 100644 --- a/Deeploy/Targets/Generic/Templates/PadTemplate.py +++ b/Deeploy/Targets/Generic/Templates/PadTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: PadTemplate.py -# -# Last edited: 27.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/QuantTemplate.py b/Deeploy/Targets/Generic/Templates/QuantTemplate.py index 8633b90302..79860652c3 100644 --- a/Deeploy/Targets/Generic/Templates/QuantTemplate.py +++ b/Deeploy/Targets/Generic/Templates/QuantTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: QuantTemplate.py -# -# Last edited: 12.03.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Federico Brancasi, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/RQAddTemplate.py b/Deeploy/Targets/Generic/Templates/RQAddTemplate.py index dacc9ac627..35593ad133 100644 --- a/Deeploy/Targets/Generic/Templates/RQAddTemplate.py +++ b/Deeploy/Targets/Generic/Templates/RQAddTemplate.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RQAddTemplate.py -# -# Last edited: 11.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/RQIntegerDivTemplate.py b/Deeploy/Targets/Generic/Templates/RQIntegerDivTemplate.py index 1f2e01c1ce..6ce4cba12f 100644 --- a/Deeploy/Targets/Generic/Templates/RQIntegerDivTemplate.py +++ b/Deeploy/Targets/Generic/Templates/RQIntegerDivTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: RQIntegerDivTemplate.py -# -# Last edited: 02.09.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/RQSiGELUTemplate.py b/Deeploy/Targets/Generic/Templates/RQSiGELUTemplate.py index 7783ade729..2d6a967936 100644 --- a/Deeploy/Targets/Generic/Templates/RQSiGELUTemplate.py +++ b/Deeploy/Targets/Generic/Templates/RQSiGELUTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: RQSiGELUTemplate.py -# -# Last edited: 13.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/RQSiHardswishTemplate.py b/Deeploy/Targets/Generic/Templates/RQSiHardswishTemplate.py index 4067ef0cf9..da2b8a78da 100644 --- a/Deeploy/Targets/Generic/Templates/RQSiHardswishTemplate.py +++ b/Deeploy/Targets/Generic/Templates/RQSiHardswishTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: RQSiHardswishTemplate.py -# -# Last edited: 23.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ReduceMeanTemplate.py b/Deeploy/Targets/Generic/Templates/ReduceMeanTemplate.py index d43d6f7456..93d884eb87 100644 --- a/Deeploy/Targets/Generic/Templates/ReduceMeanTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ReduceMeanTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: ReduceMeanTemplate.py -# -# Last edited: 05.06.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ReduceSumTemplate.py b/Deeploy/Targets/Generic/Templates/ReduceSumTemplate.py index 952efb4ce8..9fc4a301e5 100644 --- a/Deeploy/Targets/Generic/Templates/ReduceSumTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ReduceSumTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ReduceSumTemplate.py -# -# Last edited: 27.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/Generic/Templates/RequantShiftTemplate.py b/Deeploy/Targets/Generic/Templates/RequantShiftTemplate.py index 9041296c98..2fca2e0eb1 100644 --- a/Deeploy/Targets/Generic/Templates/RequantShiftTemplate.py +++ b/Deeploy/Targets/Generic/Templates/RequantShiftTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: RequantShiftTemplate.py -# -# Last edited: 14.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py b/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py index 221d9909d6..1ba3d99655 100644 --- a/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: ReshapeTemplate.py -# -# Last edited: 16.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/SkipTemplate.py b/Deeploy/Targets/Generic/Templates/SkipTemplate.py index dee5b80c12..e8453ed2fd 100644 --- a/Deeploy/Targets/Generic/Templates/SkipTemplate.py +++ b/Deeploy/Targets/Generic/Templates/SkipTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: SkipTemplate.py -# -# Last edited: 16.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/SliceTemplate.py b/Deeploy/Targets/Generic/Templates/SliceTemplate.py index b0188bbf06..3ffaa46219 100644 --- a/Deeploy/Targets/Generic/Templates/SliceTemplate.py +++ b/Deeploy/Targets/Generic/Templates/SliceTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SliceTemplate.py -# -# Last edited: 01.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/TransposeTemplate.py b/Deeploy/Targets/Generic/Templates/TransposeTemplate.py index 0dfceacb8c..bbc50bcadc 100644 --- a/Deeploy/Targets/Generic/Templates/TransposeTemplate.py +++ b/Deeploy/Targets/Generic/Templates/TransposeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: TransposeTemplate.py -# -# Last edited: 28.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/__init__.py b/Deeploy/Targets/Generic/Templates/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Generic/Templates/__init__.py +++ b/Deeploy/Targets/Generic/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Generic/Templates/iGELUTemplate.py b/Deeploy/Targets/Generic/Templates/iGELUTemplate.py index 0b3e1b8fc8..9ff716782c 100644 --- a/Deeploy/Targets/Generic/Templates/iGELUTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iGELUTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: iGELUTemplate.py -# -# Last edited: 13.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/iHardswishTemplate.py b/Deeploy/Targets/Generic/Templates/iHardswishTemplate.py index 0dd7f65aef..da10fd50e3 100644 --- a/Deeploy/Targets/Generic/Templates/iHardswishTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iHardswishTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iHardswishTemplate.py -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/iLayernormTemplate.py b/Deeploy/Targets/Generic/Templates/iLayernormTemplate.py index 75a1a9b5c0..bd14213ee7 100644 --- a/Deeploy/Targets/Generic/Templates/iLayernormTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iLayernormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: ILayernormTemplate.py -# -# Last edited: 31.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/Generic/Templates/iNoNormTemplate.py b/Deeploy/Targets/Generic/Templates/iNoNormTemplate.py index 242962e306..562b3168a9 100644 --- a/Deeploy/Targets/Generic/Templates/iNoNormTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iNoNormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iNoNormTemplate.py -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Generic/Templates/iRMSNormTemplate.py b/Deeploy/Targets/Generic/Templates/iRMSNormTemplate.py index 2f8859e026..0fe1e1338b 100644 --- a/Deeploy/Targets/Generic/Templates/iRMSNormTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iRMSNormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iRMSNormTemplate.py -# -# Last edited: 20.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Templates/iSoftmaxPreAllocatedBuffTemplate.py b/Deeploy/Targets/Generic/Templates/iSoftmaxPreAllocatedBuffTemplate.py index 45b80a7bc2..9cf609deea 100644 --- a/Deeploy/Targets/Generic/Templates/iSoftmaxPreAllocatedBuffTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iSoftmaxPreAllocatedBuffTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iSoftmaxPreAllocatedBuffTemplate.py -# -# Last edited: 09.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/Generic/Templates/iSoftmaxTemplate.py b/Deeploy/Targets/Generic/Templates/iSoftmaxTemplate.py index be5c7f1e6c..81aca29330 100644 --- a/Deeploy/Targets/Generic/Templates/iSoftmaxTemplate.py +++ b/Deeploy/Targets/Generic/Templates/iSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: iSoftmaxTemplate.py -# -# Last edited: 30.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/AddTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/AddTileConstraint.py index 0e932a89c6..e87f9abb62 100644 --- a/Deeploy/Targets/Generic/TileConstraints/AddTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/AddTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AddTileConstraint.py -# -# Last edited: 05.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .BOPTileConstraint import BOPTileConstraint diff --git a/Deeploy/Targets/Generic/TileConstraints/BOPTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/BOPTileConstraint.py index d5b77f9b8f..e1f6f0e71c 100644 --- a/Deeploy/Targets/Generic/TileConstraints/BOPTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/BOPTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: BOPTileConstraint.py -# -# Last edited: 05.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/ConcatTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/ConcatTileConstraint.py index 6e546ab1ea..1fc8967c4c 100644 --- a/Deeploy/Targets/Generic/TileConstraints/ConcatTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/ConcatTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ConcatTileConstraint.py -# -# Last edited: 19.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/MulTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/MulTileConstraint.py index f2a794ffea..9f71012ffe 100644 --- a/Deeploy/Targets/Generic/TileConstraints/MulTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/MulTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: MulTileConstraint.py -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .BOPTileConstraint import BOPTileConstraint diff --git a/Deeploy/Targets/Generic/TileConstraints/NOPTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/NOPTileConstraint.py index 73293fba9c..d24abb4ba5 100644 --- a/Deeploy/Targets/Generic/TileConstraints/NOPTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/NOPTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FlattenTileConstraint.py -# -# Last edited: 02.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List diff --git a/Deeploy/Targets/Generic/TileConstraints/RQSiGELUTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/RQSiGELUTileConstraint.py index 5bea47e35e..6c78c96734 100644 --- a/Deeploy/Targets/Generic/TileConstraints/RQSiGELUTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/RQSiGELUTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: RQSiGELUTileConstraint.py -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .UnaryTileConstraint import UnaryTileConstraint diff --git a/Deeploy/Targets/Generic/TileConstraints/RQSiHardswishTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/RQSiHardswishTileConstraint.py index 98e3fd78a9..fd81d5d9a3 100644 --- a/Deeploy/Targets/Generic/TileConstraints/RQSiHardswishTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/RQSiHardswishTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: RQiHardswishTileConstraint.py -# -# Last edited: 23.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .UnaryTileConstraint import UnaryTileConstraint diff --git a/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py index f9c94364d0..c83d8b1e2a 100644 --- a/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/TransposeTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TransposeTileConstraint.py -# -# Last edited: 01.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/UnaryTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/UnaryTileConstraint.py index 590ff87956..91e180dd2c 100644 --- a/Deeploy/Targets/Generic/TileConstraints/UnaryTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/UnaryTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: UnaryTileConstraint.py -# -# Last edited: 05.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/UntiledTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/UntiledTileConstraint.py index d9fef0eb9c..091cb55a41 100644 --- a/Deeploy/Targets/Generic/TileConstraints/UntiledTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/UntiledTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: UntiledTileConstraint.py -# -# Last edited: 03.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/Generic/TileConstraints/__init__.py b/Deeploy/Targets/Generic/TileConstraints/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Generic/TileConstraints/__init__.py +++ b/Deeploy/Targets/Generic/TileConstraints/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Generic/TileConstraints/iHardswishTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/iHardswishTileConstraint.py index 96abf977bb..d3d2e72520 100644 --- a/Deeploy/Targets/Generic/TileConstraints/iHardswishTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/iHardswishTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iHardswishTileConstraint.py -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py b/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py index e31914aa3b..b503fb5e91 100644 --- a/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py +++ b/Deeploy/Targets/Generic/TileConstraints/iRMSNormTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iRMSNormTileConstraint.py -# -# Last edited: 21.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Generic/Tiler.py b/Deeploy/Targets/Generic/Tiler.py index 35df320a4f..9e55c706ca 100644 --- a/Deeploy/Targets/Generic/Tiler.py +++ b/Deeploy/Targets/Generic/Tiler.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: BasicTiler.py -# -# Last edited: 01.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.Bindings import BasicAddBindings, BasicConcatBindings, BasicReshapeBindings, \ BasicTransposeBindings diff --git a/Deeploy/Targets/Generic/TopologyOptimizationPasses/Passes.py b/Deeploy/Targets/Generic/TopologyOptimizationPasses/Passes.py index ac6933bbbd..b881529f7e 100644 --- a/Deeploy/Targets/Generic/TopologyOptimizationPasses/Passes.py +++ b/Deeploy/Targets/Generic/TopologyOptimizationPasses/Passes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: BasicPasses.py -# -# Last edited: 28.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from collections import OrderedDict diff --git a/Deeploy/Targets/Generic/TopologyOptimizationPasses/__init__.py b/Deeploy/Targets/Generic/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Generic/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/Targets/Generic/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Generic/TypeCheckers.py b/Deeploy/Targets/Generic/TypeCheckers.py index 8b62e41e76..8f3a12ec8d 100644 --- a/Deeploy/Targets/Generic/TypeCheckers.py +++ b/Deeploy/Targets/Generic/TypeCheckers.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: BasicCheckers.py -# -# Last edited: 16.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Optional, Sequence, Type diff --git a/Deeploy/Targets/Generic/__init__.py b/Deeploy/Targets/Generic/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Generic/__init__.py +++ b/Deeploy/Targets/Generic/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/MemPool/Bindings.py b/Deeploy/Targets/MemPool/Bindings.py index 38157c6997..cea42f2d03 100644 --- a/Deeploy/Targets/MemPool/Bindings.py +++ b/Deeploy/Targets/MemPool/Bindings.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MemPoolBindings.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ diff --git a/Deeploy/Targets/MemPool/DataTypes.py b/Deeploy/Targets/MemPool/DataTypes.py index 11ed173617..fe790d28a8 100644 --- a/Deeploy/Targets/MemPool/DataTypes.py +++ b/Deeploy/Targets/MemPool/DataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: MemPoolDataTypes.py -# -# Last edited: 08.01.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from dataclasses import dataclass diff --git a/Deeploy/Targets/MemPool/Deployer.py b/Deeploy/Targets/MemPool/Deployer.py index 788fe8db59..5431320978 100644 --- a/Deeploy/Targets/MemPool/Deployer.py +++ b/Deeploy/Targets/MemPool/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MemPoolDeployer.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/MemPool/Layers.py b/Deeploy/Targets/MemPool/Layers.py index 6f0ef4b543..679b47459e 100644 --- a/Deeploy/Targets/MemPool/Layers.py +++ b/Deeploy/Targets/MemPool/Layers.py @@ -1,24 +1,3 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: MemPoolLayers.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/Deeploy/Targets/MemPool/Parsers.py b/Deeploy/Targets/MemPool/Parsers.py index 6166d1cdaf..a3081c5a3c 100644 --- a/Deeploy/Targets/MemPool/Parsers.py +++ b/Deeploy/Targets/MemPool/Parsers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MemPoolParsers.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/MemPool/Platform.py b/Deeploy/Targets/MemPool/Platform.py index 02ac39c5d7..3302d1eb12 100644 --- a/Deeploy/Targets/MemPool/Platform.py +++ b/Deeploy/Targets/MemPool/Platform.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: MemPoolPlatform.py -# -# Last edited: 05.05.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese, ETH Zurich -# - Calin Diaconu, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict diff --git a/Deeploy/Targets/MemPool/Templates/AllocateTemplate.py b/Deeploy/Targets/MemPool/Templates/AllocateTemplate.py index 0e78db4008..40e03a3773 100644 --- a/Deeploy/Targets/MemPool/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/AllocateTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/MemPool/Templates/ConvTemplate.py b/Deeploy/Targets/MemPool/Templates/ConvTemplate.py index 0eeddf086c..7539eebbf4 100644 --- a/Deeploy/Targets/MemPool/Templates/ConvTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/ConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: ConvTemplate.py -# -# Last edited: 02.12.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/DWConvTemplate.py b/Deeploy/Targets/MemPool/Templates/DWConvTemplate.py index 1a5c4f8041..27252cb74b 100644 --- a/Deeploy/Targets/MemPool/Templates/DWConvTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/DWConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: DWConvTemplate.py -# -# Last edited: 09.01.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/FreeTemplate.py b/Deeploy/Targets/MemPool/Templates/FreeTemplate.py index 899afa9896..10cffb0b18 100644 --- a/Deeploy/Targets/MemPool/Templates/FreeTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/FreeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FreeTemplate.py -# -# Last edited: 15.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/MemPool/Templates/GemmTemplate.py b/Deeploy/Targets/MemPool/Templates/GemmTemplate.py index 6a92c7e7c6..e5d53bd255 100644 --- a/Deeploy/Targets/MemPool/Templates/GemmTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/GemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GemmTemplate.py -# -# Last edited: 16.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py b/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py index acad82fe28..6bc8596a51 100644 --- a/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/ITAMaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ITAMaxTemplate.py -# -# Last edited: 27.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/ITATemplate.py b/Deeploy/Targets/MemPool/Templates/ITATemplate.py index 40f76c50cd..2905210048 100644 --- a/Deeploy/Targets/MemPool/Templates/ITATemplate.py +++ b/Deeploy/Targets/MemPool/Templates/ITATemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ITATemplate.py -# -# Last edited: 16.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/MHSATemplate.py b/Deeploy/Targets/MemPool/Templates/MHSATemplate.py index ed208d311c..c5e8322dea 100644 --- a/Deeploy/Targets/MemPool/Templates/MHSATemplate.py +++ b/Deeploy/Targets/MemPool/Templates/MHSATemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MHSATemplate.py -# -# Last edited: 30.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/MatMulTemplate.py b/Deeploy/Targets/MemPool/Templates/MatMulTemplate.py index 400d556dc3..062ba3cc9e 100644 --- a/Deeploy/Targets/MemPool/Templates/MatMulTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/MatMulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MatMulTemplate.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/MaxPoolTemplate.py b/Deeploy/Targets/MemPool/Templates/MaxPoolTemplate.py index 92adc98624..c57bbade77 100644 --- a/Deeploy/Targets/MemPool/Templates/MaxPoolTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/MaxPoolTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MaxPoolTemplate.py -# -# Last edited: 13.12.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py b/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py index 7806a66485..e6a42768e8 100644 --- a/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/RQGemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RQGemmTemplate.py -# -# Last edited: 17.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py b/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py index db04b500e6..76ad029fb4 100644 --- a/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/RQMatMulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RQMatMulTemplate.py -# -# Last edited: 02.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/RequantShiftTemplate.py b/Deeploy/Targets/MemPool/Templates/RequantShiftTemplate.py index bc1ca14404..7898790af0 100644 --- a/Deeploy/Targets/MemPool/Templates/RequantShiftTemplate.py +++ b/Deeploy/Targets/MemPool/Templates/RequantShiftTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RequantShiftTemplate.py -# -# Last edited: 24.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/MemPool/Templates/__init__.py b/Deeploy/Targets/MemPool/Templates/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/MemPool/Templates/__init__.py +++ b/Deeploy/Targets/MemPool/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/MemPool/TopologyOptimizationPasses/Passes.py b/Deeploy/Targets/MemPool/TopologyOptimizationPasses/Passes.py index 56b2683f9a..49f317caa4 100644 --- a/Deeploy/Targets/MemPool/TopologyOptimizationPasses/Passes.py +++ b/Deeploy/Targets/MemPool/TopologyOptimizationPasses/Passes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: MemPoolPasses.py -# -# Last edited: 13.11.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from functools import partial from typing import Dict, Union diff --git a/Deeploy/Targets/MemPool/TopologyOptimizationPasses/__init__.py b/Deeploy/Targets/MemPool/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/MemPool/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/Targets/MemPool/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/MemPool/__init__.py b/Deeploy/Targets/MemPool/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/MemPool/__init__.py +++ b/Deeploy/Targets/MemPool/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Neureka/Bindings.py b/Deeploy/Targets/Neureka/Bindings.py index 2a62cd58e5..010d29db01 100644 --- a/Deeploy/Targets/Neureka/Bindings.py +++ b/Deeploy/Targets/Neureka/Bindings.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: NeurekaBindings.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# Luka Macan, University of Bologna -# Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import int8_t, int32_t, uint8_t diff --git a/Deeploy/Targets/Neureka/Deployer.py b/Deeploy/Targets/Neureka/Deployer.py index c14d1abec1..e9b966569a 100644 --- a/Deeploy/Targets/Neureka/Deployer.py +++ b/Deeploy/Targets/Neureka/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Deployer.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/Neureka/Engine.py b/Deeploy/Targets/Neureka/Engine.py index 7775f415fb..5d52840f62 100644 --- a/Deeploy/Targets/Neureka/Engine.py +++ b/Deeploy/Targets/Neureka/Engine.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Engine.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List diff --git a/Deeploy/Targets/Neureka/Parsers.py b/Deeploy/Targets/Neureka/Parsers.py index caa1881e17..3c564c10b2 100644 --- a/Deeploy/Targets/Neureka/Parsers.py +++ b/Deeploy/Targets/Neureka/Parsers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Parsers.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/Neureka/Platform.py b/Deeploy/Targets/Neureka/Platform.py index b618cabdad..04e92468d4 100644 --- a/Deeploy/Targets/Neureka/Platform.py +++ b/Deeploy/Targets/Neureka/Platform.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Platform.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Optional diff --git a/Deeploy/Targets/Neureka/Templates/AllocateTemplate.py b/Deeploy/Targets/Neureka/Templates/AllocateTemplate.py index 5a39360113..ef8897e84c 100644 --- a/Deeploy/Targets/Neureka/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/Neureka/Templates/AllocateTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 09.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Neureka/Templates/ConvTemplate.py b/Deeploy/Targets/Neureka/Templates/ConvTemplate.py index 2d658cc1ca..97253d6e12 100644 --- a/Deeploy/Targets/Neureka/Templates/ConvTemplate.py +++ b/Deeploy/Targets/Neureka/Templates/ConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ConvTemplate.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from abc import abstractmethod from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Neureka/Templates/__init__.py b/Deeploy/Targets/Neureka/Templates/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Neureka/Templates/__init__.py +++ b/Deeploy/Targets/Neureka/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py index 70eea8772a..a5cacf298c 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: NeurekaDenseConstraint.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py index 0a0e7153ec..d0e32597cc 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: NeurekaDepthwiseConstraint.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py index c9bdf6a12e..a780214e16 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: NeurekaPointwiseConstraint.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Neureka/TileConstraints/__init__.py b/Deeploy/Targets/Neureka/TileConstraints/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/__init__.py +++ b/Deeploy/Targets/Neureka/TileConstraints/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Neureka/Tiler.py b/Deeploy/Targets/Neureka/Tiler.py index e4f07c1dda..775294d8e0 100644 --- a/Deeploy/Targets/Neureka/Tiler.py +++ b/Deeploy/Targets/Neureka/Tiler.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Tiler.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Neureka.Bindings import NeurekaDenseConv2DBindings, NeurekaDWConv2DBindings, \ diff --git a/Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py b/Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py index f3fdeafcb0..84e0565b97 100644 --- a/Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py +++ b/Deeploy/Targets/Neureka/TopologyOptimizationPasses/Passes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: Passes.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import itertools import math diff --git a/Deeploy/Targets/Neureka/TopologyOptimizationPasses/__init__.py b/Deeploy/Targets/Neureka/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Neureka/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/Targets/Neureka/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Neureka/__init__.py b/Deeploy/Targets/Neureka/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/Neureka/__init__.py +++ b/Deeploy/Targets/Neureka/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/PULPOpen/Bindings.py b/Deeploy/Targets/PULPOpen/Bindings.py index 1898f00aff..9ff940b2f0 100644 --- a/Deeploy/Targets/PULPOpen/Bindings.py +++ b/Deeploy/Targets/PULPOpen/Bindings.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPBindings.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurichs -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import itertools from functools import partial diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py index 42b090776f..6bc9d0ac24 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/AutoTransposeUtils.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AutoTransposeUtils.py -# -# Last edited: 11.12.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import Dict, List, Literal, Tuple diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterSynch.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterSynch.py index 275c8baa9c..3d49501ea7 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterSynch.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterSynch.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPClusterSynch.py -# -# Last edited: 30.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py index b81d043dd2..7f503a5da3 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: PULPClusterTiling.py -# -# Last edited: 19.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py index 32854b3e93..646f179d9c 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: PULPL3Tiling.py -# -# Last edited: 19.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPProfileUntiled.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPProfileUntiled.py index c8c9b06fb9..69fe52bcb2 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPProfileUntiled.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPProfileUntiled.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: PULPClusterTiling.py -# -# Last edited: 19.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/__init__.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/__init__.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py index 1d82e983d1..849db08576 100644 --- a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py +++ b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: L3Dma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Dict, Tuple diff --git a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py index ee524849de..a640973672 100644 --- a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py +++ b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: MchanDma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Dict, Tuple diff --git a/Deeploy/Targets/PULPOpen/DataTypes.py b/Deeploy/Targets/PULPOpen/DataTypes.py index 8b53cbc439..43e60a81ce 100644 --- a/Deeploy/Targets/PULPOpen/DataTypes.py +++ b/Deeploy/Targets/PULPOpen/DataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPDataTypes.py -# -# Last edited: 01.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from dataclasses import dataclass from functools import partial diff --git a/Deeploy/Targets/PULPOpen/Deployer.py b/Deeploy/Targets/PULPOpen/Deployer.py index d501863cb4..86bf02e578 100644 --- a/Deeploy/Targets/PULPOpen/Deployer.py +++ b/Deeploy/Targets/PULPOpen/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPDeployer.py -# -# Last edited: 08.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, List, Type diff --git a/Deeploy/Targets/PULPOpen/Layers.py b/Deeploy/Targets/PULPOpen/Layers.py index d291078c88..69ce2fa958 100644 --- a/Deeploy/Targets/PULPOpen/Layers.py +++ b/Deeploy/Targets/PULPOpen/Layers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: CMSISLayers.py -# -# Last edited: 22.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Parsers.py b/Deeploy/Targets/PULPOpen/Parsers.py index 4d5359db95..e94af6e420 100644 --- a/Deeploy/Targets/PULPOpen/Parsers.py +++ b/Deeploy/Targets/PULPOpen/Parsers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPParsers.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Tuple diff --git a/Deeploy/Targets/PULPOpen/Platform.py b/Deeploy/Targets/PULPOpen/Platform.py index fd014e82c6..dce02b2efe 100644 --- a/Deeploy/Targets/PULPOpen/Platform.py +++ b/Deeploy/Targets/PULPOpen/Platform.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPPlatform.py -# -# Last edited: 07.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import numpy as np import onnx_graphsurgeon as gs diff --git a/Deeploy/Targets/PULPOpen/Templates/AllocateTemplate.py b/Deeploy/Targets/PULPOpen/Templates/AllocateTemplate.py index d6617264e6..468a12dd73 100644 --- a/Deeploy/Targets/PULPOpen/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/AllocateTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 09.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/ConvTemplate.py b/Deeploy/Targets/PULPOpen/Templates/ConvTemplate.py index 7ceec56b13..ebc614f479 100644 --- a/Deeploy/Targets/PULPOpen/Templates/ConvTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/ConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ConvTemplate.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py index 850de69e55..7f1c2e21c6 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatAddTemplate.py -# -# Last edited: 13.11.2024 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Authors: -# - Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py index 563639a90b..29a216d728 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FLoatConvTemplate.py -# -# Last edited: 23.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatGELUTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatGELUTemplate.py index 1ff52a2b0b..df2a178662 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatGELUTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatGELUTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatGELUTemplate.py -# -# Last edited: 04.05.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py index 9f7fa4bc95..f4c22b2c22 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py @@ -1,27 +1,7 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatGemmTemplate.py.py -# -# Last edited: 05.06.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the Licens + from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py index 2040c85fef..9d4f60e8fc 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatLayernormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatLayernormTemplate.py -# -# Last edited: 05.06.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py index cd6d17b01e..11b7c9aa2a 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py @@ -1,27 +1,7 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Fï¼›FloatMatMul.py -# -# Last edited: 28.03.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the Licens + from Deeploy.DeeployTypes import NodeTemplate referenceTemplate = NodeTemplate(""" diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py index f32d98cf50..846aeae92d 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMaxPoolTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MaxPoolTemplate.py -# -# Last edited: 24.01.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py index bbed92ce74..2f202b24d2 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatMulTemplate.py -# -# Last edited: 05.06.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Authors: -# - Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatReluTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatReluTemplate.py index f7aed10e0d..ab22b75bee 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatReluTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatReluTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FloatReluTemplate.py -# -# Last edited: 04.05.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatSoftmaxTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatSoftmaxTemplate.py index 6e2905630a..b12a15c7b0 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatSoftmaxTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: FloatSoftmaxTemplate.py -# -# Last edited: 23.1.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/FreeTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FreeTemplate.py index de10f7f8aa..639f707e9f 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FreeTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FreeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: FreeTemplate.py -# -# Last edited: 09.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/GEMMTemplate.py b/Deeploy/Targets/PULPOpen/Templates/GEMMTemplate.py index 0486dd18f5..1f7149e1e8 100644 --- a/Deeploy/Targets/PULPOpen/Templates/GEMMTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/GEMMTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GEMMTemplate.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/MatrixVectorTemplate.py b/Deeploy/Targets/PULPOpen/Templates/MatrixVectorTemplate.py index 359619384a..e4b8348614 100644 --- a/Deeploy/Targets/PULPOpen/Templates/MatrixVectorTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/MatrixVectorTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: MatrixVectorTemplate.py -# -# Last edited: 15.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/MaxPool2DTemplate.py b/Deeploy/Targets/PULPOpen/Templates/MaxPool2DTemplate.py index 6b74c3d73f..d4b63a2694 100644 --- a/Deeploy/Targets/PULPOpen/Templates/MaxPool2DTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/MaxPool2DTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MaxPool2DTemplate.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/MulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/MulTemplate.py index 1b6be3ddcd..1dbefa3287 100644 --- a/Deeploy/Targets/PULPOpen/Templates/MulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/MulTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: MulTemplate.py -# -# Last edited: 15.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate, OperatorRepresentation diff --git a/Deeploy/Targets/PULPOpen/Templates/RQAddTemplate.py b/Deeploy/Targets/PULPOpen/Templates/RQAddTemplate.py index f88b2dbacc..1cbf9d9764 100644 --- a/Deeploy/Targets/PULPOpen/Templates/RQAddTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/RQAddTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RQAddTemplate.py -# -# Last edited: 11.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.Templates.RQAddTemplate import RQAddTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/RQSiHardswishTemplate.py b/Deeploy/Targets/PULPOpen/Templates/RQSiHardswishTemplate.py index 462f176097..8b4f02d0b0 100644 --- a/Deeploy/Targets/PULPOpen/Templates/RQSiHardswishTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/RQSiHardswishTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: RQSiHardswishTemplate.py -# -# Last edited: 15.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/ReduceMeanTemplate.py b/Deeploy/Targets/PULPOpen/Templates/ReduceMeanTemplate.py index 14948844ff..849f68eef3 100644 --- a/Deeploy/Targets/PULPOpen/Templates/ReduceMeanTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/ReduceMeanTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: ReduceMeanTemplate.py -# -# Last edited: 05.06.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/RequantShiftTemplate.py b/Deeploy/Targets/PULPOpen/Templates/RequantShiftTemplate.py index 4a7a384171..791f3661cd 100644 --- a/Deeploy/Targets/PULPOpen/Templates/RequantShiftTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/RequantShiftTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: RequantShiftTemplate.py -# -# Last edited: 14.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py b/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py index 4d36a047af..b209a76653 100644 --- a/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/SGDTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SGDTemplate.py -# -# Last edited: 21.03.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py b/Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py index 07b6afcbaa..ae400ad216 100644 --- a/Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SliceTemplate.py -# -# Last edited: 01.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py b/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py index d81bda4bb9..c1aefe01a3 100644 --- a/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/SoftmaxCrossEntropyLossTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: SoftmaxCrossEntropyTemplate.py -# -# Last edited: 09.03.2025 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py b/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py index 65cfdd94ba..76fd47cfb6 100644 --- a/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/TallGEMMTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: TallGEMMTemplate.py -# -# Last edited: 21.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/TransposeTemplate.py b/Deeploy/Targets/PULPOpen/Templates/TransposeTemplate.py index 5a01c73bdd..65c2285e24 100644 --- a/Deeploy/Targets/PULPOpen/Templates/TransposeTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/TransposeTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna # -# File: TransposeTemplate.py -# -# Last edited: 28.12.2021 -# -# Copyright (C) 2021, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py b/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py index 928b50e9e5..d712b3a517 100644 --- a/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/UniformRequantShiftTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: UniformRequantShiftTemplate.py -# -# Last edited: 12.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/__init__.py b/Deeploy/Targets/PULPOpen/Templates/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/PULPOpen/Templates/__init__.py +++ b/Deeploy/Targets/PULPOpen/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/PULPOpen/Templates/iRMSNormTemplate.py b/Deeploy/Targets/PULPOpen/Templates/iRMSNormTemplate.py index 63e5d0e66f..0aa91cc8f5 100644 --- a/Deeploy/Targets/PULPOpen/Templates/iRMSNormTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/iRMSNormTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iRMSNormTemplate.py -# -# Last edited: 20.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/Templates/iSoftmaxTemplate.py b/Deeploy/Targets/PULPOpen/Templates/iSoftmaxTemplate.py index 804db3b7e0..af3a93a185 100644 --- a/Deeploy/Targets/PULPOpen/Templates/iSoftmaxTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/iSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: iSoftmaxTemplate.py -# -# Last edited: 13.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/ConvTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/ConvTileConstraint.py index 8af20e3df3..c69760df59 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/ConvTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/ConvTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ConvTileConstraint.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/DWConvTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/DWConvTileConstraint.py index d4e1989061..8d54eea437 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/DWConvTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/DWConvTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: ConvTileConstraint.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py index ea5c7d0cb4..2f747a4002 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/GEMMTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: GEMMTileConstraint.py -# -# Last edited: 02.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/GatherTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/GatherTileConstraint.py index 036f8adf35..3526e3d8bb 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/GatherTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/GatherTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ConcatTileConstraint.py -# -# Last edited: 19.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py index 66cfcd8211..5f43ad7534 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/LayernormTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: LayernormTileConstraint.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py index 1c04adb986..8b795be88e 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/MatMulTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MatMulTileConstraint.py -# -# Last edited: 04.07.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/MaxPoolTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/MaxPoolTileConstraint.py index 695ba15812..c0fab8f028 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/MaxPoolTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/MaxPoolTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MaxPoolTileConstraint.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/RequantShiftTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/RequantShiftTileConstraint.py index da3acf015d..eab0c3a4fd 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/RequantShiftTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/RequantShiftTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RequantShiftTileConstraint.py -# -# Last edited: 05.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/SGDTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/SGDTileConstraint.py index 2a4477bcb1..b7757786e1 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/SGDTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/SGDTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: AddTileConstraint.py -# -# Last edited: 21.03.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.TileConstraints.BOPTileConstraint import BOPTileConstraint diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py index cec95f671d..38c984de63 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/SoftmaxCrossEntropyTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: SoftmaxCrossEntropyTileConstraint.py -# -# Last edited: 19.03.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Run Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/__init__.py b/Deeploy/Targets/PULPOpen/TileConstraints/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/__init__.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/PULPOpen/TileConstraints/iSoftmaxTileConstraint.py b/Deeploy/Targets/PULPOpen/TileConstraints/iSoftmaxTileConstraint.py index 9fb2a6f272..1b5eddb51a 100644 --- a/Deeploy/Targets/PULPOpen/TileConstraints/iSoftmaxTileConstraint.py +++ b/Deeploy/Targets/PULPOpen/TileConstraints/iSoftmaxTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: iSoftmaxTileConstraint.py -# -# Last edited: 13.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/PULPOpen/Tiler.py b/Deeploy/Targets/PULPOpen/Tiler.py index dbca111478..a6dbaa4e87 100644 --- a/Deeploy/Targets/PULPOpen/Tiler.py +++ b/Deeploy/Targets/PULPOpen/Tiler.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPTiler.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy diff --git a/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.py b/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.py index aabcbb5928..43d490e80b 100644 --- a/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.py +++ b/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/Passes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPPasses.py -# -# Last edited: 10.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from collections import OrderedDict diff --git a/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/__init__.py b/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/__init__.py +++ b/Deeploy/Targets/PULPOpen/TopologyOptimizationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/PULPOpen/TypeCheckers.py b/Deeploy/Targets/PULPOpen/TypeCheckers.py index 2685f4d7fc..e309624186 100644 --- a/Deeploy/Targets/PULPOpen/TypeCheckers.py +++ b/Deeploy/Targets/PULPOpen/TypeCheckers.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPCheckers.py -# -# Last edited: 03.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Sequence, Type diff --git a/Deeploy/Targets/PULPOpen/__init__.py b/Deeploy/Targets/PULPOpen/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/PULPOpen/__init__.py +++ b/Deeploy/Targets/PULPOpen/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/Snitch/Bindings.py b/Deeploy/Targets/Snitch/Bindings.py index 391c64af81..e9be18a535 100644 --- a/Deeploy/Targets/Snitch/Bindings.py +++ b/Deeploy/Targets/Snitch/Bindings.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchBindings.py -# -# Last edited: 30.05.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from functools import partial diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterSynch.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterSynch.py index 8173b93ebb..cc0af164ad 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterSynch.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterSynch.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchClusterSynch.py -# -# Last edited: 31.05.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py index 71268d0a6d..30213d3147 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchClusterTiling.py -# -# Last edited: 31.05.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchCoreFilter.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchCoreFilter.py index 6ea21f478b..a864c5db8f 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchCoreFilter.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchCoreFilter.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchCoreFilter.py -# -# Last edited: 04.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, luka.macan@unibo.it, University of Bologna -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Literal, Tuple diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchProfileExecutionBlock.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchProfileExecutionBlock.py index 7559a1a54c..ec17b36011 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchProfileExecutionBlock.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchProfileExecutionBlock.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchProfileExecutionBlock.py -# -# Last edited: 05.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/__init__.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/__init__.py index d3281dd173..a45f50652e 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/__init__.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/__init__.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .SnitchClusterSynch import * from .SnitchClusterTiling import * diff --git a/Deeploy/Targets/Snitch/DMA/SnitchDma.py b/Deeploy/Targets/Snitch/DMA/SnitchDma.py index 236448e426..aea1f03007 100644 --- a/Deeploy/Targets/Snitch/DMA/SnitchDma.py +++ b/Deeploy/Targets/Snitch/DMA/SnitchDma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: SnitchDma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/Deeploy/Targets/Snitch/DataTypes.py b/Deeploy/Targets/Snitch/DataTypes.py index b1d3a92eda..16cd6e8cbe 100644 --- a/Deeploy/Targets/Snitch/DataTypes.py +++ b/Deeploy/Targets/Snitch/DataTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchDataTypes.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.AbstractDataTypes import PointerClass, Struct, VoidType from Deeploy.CommonExtensions.DataTypes import uint16_t diff --git a/Deeploy/Targets/Snitch/Deployer.py b/Deeploy/Targets/Snitch/Deployer.py index ff32066902..7c3922a6bb 100644 --- a/Deeploy/Targets/Snitch/Deployer.py +++ b/Deeploy/Targets/Snitch/Deployer.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchDeployer.py -# -# Last edited: 23.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/Snitch/Parsers.py b/Deeploy/Targets/Snitch/Parsers.py index dfd32484cb..0051994686 100644 --- a/Deeploy/Targets/Snitch/Parsers.py +++ b/Deeploy/Targets/Snitch/Parsers.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchParsers.py -# -# Last edited: 07.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Luka Macan, luka.macan@unibo.it, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the Lic -# ense is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple diff --git a/Deeploy/Targets/Snitch/Platform.py b/Deeploy/Targets/Snitch/Platform.py index b6bed5a57a..1a9e714081 100644 --- a/Deeploy/Targets/Snitch/Platform.py +++ b/Deeploy/Targets/Snitch/Platform.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchPlatform.py -# -# Last edited: 23.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List diff --git a/Deeploy/Targets/Snitch/Templates/AddTemplate.py b/Deeploy/Targets/Snitch/Templates/AddTemplate.py index 3354bdfa4a..428f087300 100644 --- a/Deeploy/Targets/Snitch/Templates/AddTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/AddTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: AddTemplate.py -# -# Last edited: 11.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/Templates/AllocateTemplate.py b/Deeploy/Targets/Snitch/Templates/AllocateTemplate.py index aa37b58df5..6c1d898645 100644 --- a/Deeploy/Targets/Snitch/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/AllocateTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 23.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py b/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py index fdbc71e901..17729a2eec 100644 --- a/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/FloatGemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: FloatGemmTemplate.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py b/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py index 15bce0a1d9..216ff35b9a 100644 --- a/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/FloatSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iSoftmaxTemplate.py -# -# Last edited: 30.05.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/Templates/FreeTemplate.py b/Deeploy/Targets/Snitch/Templates/FreeTemplate.py index 39e08ef429..e8e5fbe4d9 100644 --- a/Deeploy/Targets/Snitch/Templates/FreeTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/FreeTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: FreeTemplate.py -# -# Last edited: 23.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/Snitch/Templates/GemmTemplate.py b/Deeploy/Targets/Snitch/Templates/GemmTemplate.py index 12fadbf577..d72b3c11f2 100644 --- a/Deeploy/Targets/Snitch/Templates/GemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/GemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/Templates/RQAddTemplate.py b/Deeploy/Targets/Snitch/Templates/RQAddTemplate.py index afc637c21a..ceacb1c657 100644 --- a/Deeploy/Targets/Snitch/Templates/RQAddTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/RQAddTemplate.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: RQAddTemplate.py -# -# Last edited: 11.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.Templates.RQAddTemplate import RQAddTemplate diff --git a/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py b/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py index c257c36d86..f77b6d6127 100644 --- a/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/RqGemmTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: RqGemmTemplate.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/Templates/__init__.py b/Deeploy/Targets/Snitch/Templates/__init__.py index cc12bda690..aa29624681 100644 --- a/Deeploy/Targets/Snitch/Templates/__init__.py +++ b/Deeploy/Targets/Snitch/Templates/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * \ No newline at end of file diff --git a/Deeploy/Targets/Snitch/Templates/iSoftmaxTemplate.py b/Deeploy/Targets/Snitch/Templates/iSoftmaxTemplate.py index 9a15d91104..b4b5abbf16 100644 --- a/Deeploy/Targets/Snitch/Templates/iSoftmaxTemplate.py +++ b/Deeploy/Targets/Snitch/Templates/iSoftmaxTemplate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iSoftmaxTemplate.py -# -# Last edited: 30.05.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.Templates.iSoftmaxPreAllocatedBuffTemplate import iSoftmaxPreAllocatedBuffTemplate diff --git a/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py index 58a4b5cb44..e5d35c4a42 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/GemmTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: GemmTileConstraint.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py index 6708273dfa..47bf7e29cc 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/RqGemmTileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: RqGemmTileConstraint.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/TileConstraints/__init__.py b/Deeploy/Targets/Snitch/TileConstraints/__init__.py index 93b3563586..947a6fd82a 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/__init__.py +++ b/Deeploy/Targets/Snitch/TileConstraints/__init__.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * from .iNoNormTileConstraint import * diff --git a/Deeploy/Targets/Snitch/TileConstraints/iNoNormTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/iNoNormTileConstraint.py index ab7b0cf10d..770b78902c 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/iNoNormTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/iNoNormTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: iNoNormTileConstraint.py -# -# Last edited: 06.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple diff --git a/Deeploy/Targets/Snitch/TileConstraints/iSoftmaxTileConstraint.py b/Deeploy/Targets/Snitch/TileConstraints/iSoftmaxTileConstraint.py index 55284915a3..aa405bbcb6 100644 --- a/Deeploy/Targets/Snitch/TileConstraints/iSoftmaxTileConstraint.py +++ b/Deeploy/Targets/Snitch/TileConstraints/iSoftmaxTileConstraint.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: iSoftmaxTileConstraint.py -# -# Last edited: 13.11.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, List, Tuple, Union diff --git a/Deeploy/Targets/Snitch/Tiler.py b/Deeploy/Targets/Snitch/Tiler.py index 38ba29f2dd..475a425779 100644 --- a/Deeploy/Targets/Snitch/Tiler.py +++ b/Deeploy/Targets/Snitch/Tiler.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SnitchTiler.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.Targets.Generic.TileConstraints.AddTileConstraint import AddTileConstraint from Deeploy.Targets.Snitch.Bindings import SnitchAddBindings, SnitchGemmBindings, SnitchiNoNormBindings, \ diff --git a/Deeploy/Targets/Snitch/__init__.py b/Deeploy/Targets/Snitch/__init__.py index cc12bda690..aa29624681 100644 --- a/Deeploy/Targets/Snitch/__init__.py +++ b/Deeploy/Targets/Snitch/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * \ No newline at end of file diff --git a/Deeploy/Targets/SoftHier/Deployer.py b/Deeploy/Targets/SoftHier/Deployer.py index db3b1081ec..e4ab37f299 100644 --- a/Deeploy/Targets/SoftHier/Deployer.py +++ b/Deeploy/Targets/SoftHier/Deployer.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: SoftHierDeployer.py -# -# Last edited: 03.04.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Bowen Wang , ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Type diff --git a/Deeploy/Targets/SoftHier/Platform.py b/Deeploy/Targets/SoftHier/Platform.py index f56093d142..8c0c0f6e5e 100644 --- a/Deeploy/Targets/SoftHier/Platform.py +++ b/Deeploy/Targets/SoftHier/Platform.py @@ -1,26 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: SoftHierPlatform.py -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Bowen Wang , ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import numpy as np diff --git a/Deeploy/Targets/SoftHier/Templates/AllocateTemplate.py b/Deeploy/Targets/SoftHier/Templates/AllocateTemplate.py index 66bf552f67..30da2d1998 100644 --- a/Deeploy/Targets/SoftHier/Templates/AllocateTemplate.py +++ b/Deeploy/Targets/SoftHier/Templates/AllocateTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: AllocateTemplate.py -# -# Last edited: 07.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# Bowen Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/SoftHier/Templates/FreeTemplate.py b/Deeploy/Targets/SoftHier/Templates/FreeTemplate.py index bcd78952bc..f798c9e5ab 100644 --- a/Deeploy/Targets/SoftHier/Templates/FreeTemplate.py +++ b/Deeploy/Targets/SoftHier/Templates/FreeTemplate.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: FreeTemplate.py -# -# Last edited: 07.06.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# Bowen Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from Deeploy.DeeployTypes import NodeTemplate diff --git a/Deeploy/Targets/SoftHier/Templates/__init__.py b/Deeploy/Targets/SoftHier/Templates/__init__.py index e86f60fbe6..be436b64a3 100644 --- a/Deeploy/Targets/SoftHier/Templates/__init__.py +++ b/Deeploy/Targets/SoftHier/Templates/__init__.py @@ -1,27 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 07.06.2025 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# Bowen Wang, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/Targets/__init__.py b/Deeploy/Targets/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/Targets/__init__.py +++ b/Deeploy/Targets/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/TilingExtension/AsyncDma.py b/Deeploy/TilingExtension/AsyncDma.py index 2b2bfef369..63efbda17f 100644 --- a/Deeploy/TilingExtension/AsyncDma.py +++ b/Deeploy/TilingExtension/AsyncDma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: AsyncDma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from abc import ABC, abstractmethod diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py index dc7a790604..3d0e5b7018 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: PULPClusterTilingDB.py -# -# Last edited: 25.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy import math diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py index 52c8568efc..bc863e8d22 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: PULPL3TilingSB.py -# -# Last edited: 19.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from typing import Dict, List, Set, Tuple diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py index db5a1a3fce..0db3109aea 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TilingCodeGeneration.py -# -# Last edited: 24.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy import math diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py index b47aa5888a..f1a6b1ca23 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingHoistingMixIn.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: TilingHoistingMixIn.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import List, Mapping, Optional, Sequence, Tuple, Type, TypeVar, Union diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py index 9108ab5024..1a875b626b 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: TilingPrototypes.py -# -# Last edited: 17.04.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from abc import ABC, abstractmethod from dataclasses import dataclass diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py index 3810260b75..76eacd10dd 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingVariableReplacement.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TilingVariableReplacement.py -# -# Last edited: 28.09.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy import itertools diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/__init__.py b/Deeploy/TilingExtension/CodeTransformationPasses/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/__init__.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/TilingExtension/GenericFlow.py b/Deeploy/TilingExtension/GenericFlow.py index 626bef0bf7..cdb2d5c728 100644 --- a/Deeploy/TilingExtension/GenericFlow.py +++ b/Deeploy/TilingExtension/GenericFlow.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Flow.py -# -# Last edited: 28.07.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from abc import abstractmethod from dataclasses import dataclass diff --git a/Deeploy/TilingExtension/HtmlTemplates.py b/Deeploy/TilingExtension/HtmlTemplates.py index 9466fd966f..5755621489 100644 --- a/Deeploy/TilingExtension/HtmlTemplates.py +++ b/Deeploy/TilingExtension/HtmlTemplates.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: HtmlTemplates.py -# -# Last edited: 20.03.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. # Create Monad that take a Deployer and make it TilerAware # Define Tiler Obj centralize all tilling related functionalities for a given deployer. diff --git a/Deeploy/TilingExtension/MemoryConstraintFlows.py b/Deeploy/TilingExtension/MemoryConstraintFlows.py index 4696498ef5..4e74945d92 100644 --- a/Deeploy/TilingExtension/MemoryConstraintFlows.py +++ b/Deeploy/TilingExtension/MemoryConstraintFlows.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryConstraintFlows.py -# -# Last edited: 01.08.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from collections import namedtuple diff --git a/Deeploy/TilingExtension/MemoryConstraints.py b/Deeploy/TilingExtension/MemoryConstraints.py index 60d035ae1a..756a6ccc48 100644 --- a/Deeploy/TilingExtension/MemoryConstraints.py +++ b/Deeploy/TilingExtension/MemoryConstraints.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryConstraints.py -# -# Last edited: 27.07.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/Deeploy/TilingExtension/MemoryScheduler.py b/Deeploy/TilingExtension/MemoryScheduler.py index cc0df4846d..71e4ebea88 100644 --- a/Deeploy/TilingExtension/MemoryScheduler.py +++ b/Deeploy/TilingExtension/MemoryScheduler.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: MemoryScheduler.py -# -# Last edited: 06.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/Deeploy/TilingExtension/TileConstraint.py b/Deeploy/TilingExtension/TileConstraint.py index e73cd3b615..5b067b2ce9 100644 --- a/Deeploy/TilingExtension/TileConstraint.py +++ b/Deeploy/TilingExtension/TileConstraint.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TileConstraint.py -# -# Last edited: 26.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy from abc import abstractmethod diff --git a/Deeploy/TilingExtension/TilerExtension.py b/Deeploy/TilingExtension/TilerExtension.py index 0e79178c28..dedb1d1d1b 100644 --- a/Deeploy/TilingExtension/TilerExtension.py +++ b/Deeploy/TilingExtension/TilerExtension.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: TilerExtension.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. # Create Monad that take a Deployer and make it TilerAware # Define Tiler Obj centralize all tilling related functionalities for a given deployer. diff --git a/Deeploy/TilingExtension/TilerModel.py b/Deeploy/TilingExtension/TilerModel.py index fb3645e0f6..8fb1c5ba74 100644 --- a/Deeploy/TilingExtension/TilerModel.py +++ b/Deeploy/TilingExtension/TilerModel.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TilerModel.py -# -# Last edited: 25.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# - Moritz Scherer, scheremo@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from dataclasses import dataclass from pprint import pformat diff --git a/Deeploy/TilingExtension/TilingCodegen.py b/Deeploy/TilingExtension/TilingCodegen.py index 37e032064a..604ba23c9d 100644 --- a/Deeploy/TilingExtension/TilingCodegen.py +++ b/Deeploy/TilingExtension/TilingCodegen.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: TilingCodegen.py -# -# Last edited: 11.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/Deeploy/TilingExtension/__init__.py b/Deeploy/TilingExtension/__init__.py index b50445f83c..be436b64a3 100644 --- a/Deeploy/TilingExtension/__init__.py +++ b/Deeploy/TilingExtension/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 10.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/Deeploy/__init__.py b/Deeploy/__init__.py index 65ec809815..be436b64a3 100644 --- a/Deeploy/__init__.py +++ b/Deeploy/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/DeeployTest/CMakeLists.txt b/DeeployTest/CMakeLists.txt index 6dad44829f..0634b4ba0f 100644 --- a/DeeployTest/CMakeLists.txt +++ b/DeeployTest/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 include_directories(${GENERATED_SOURCE}) diff --git a/DeeployTest/Platforms/Chimera/CMakeLists.txt b/DeeployTest/Platforms/Chimera/CMakeLists.txt index ba583f44a8..a424729cc3 100644 --- a/DeeployTest/Platforms/Chimera/CMakeLists.txt +++ b/DeeployTest/Platforms/Chimera/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/Chimera/main.c b/DeeployTest/Platforms/Chimera/main.c index 425aafa265..1beda44640 100644 --- a/DeeployTest/Platforms/Chimera/main.c +++ b/DeeployTest/Platforms/Chimera/main.c @@ -1,9 +1,7 @@ /* - * Copyright 2025 ETH Zurich. - * Licensed under the Apache License, Version 2.0, see LICENSE for details. - * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * Victor Jung + * SPDX-License-Identifier: Apache-2.0 */ #include diff --git a/DeeployTest/Platforms/Generic/CMakeLists.txt b/DeeployTest/Platforms/Generic/CMakeLists.txt index 6c22e993c7..f97f1cdf1b 100644 --- a/DeeployTest/Platforms/Generic/CMakeLists.txt +++ b/DeeployTest/Platforms/Generic/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/Generic/main.c b/DeeployTest/Platforms/Generic/main.c index ebfa116fd6..e2b0449fb5 100644 --- a/DeeployTest/Platforms/Generic/main.c +++ b/DeeployTest/Platforms/Generic/main.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: main.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/DeeployTest/Platforms/MemPool/CMakeLists.txt b/DeeployTest/Platforms/MemPool/CMakeLists.txt index 8faa483dc4..e237425c58 100644 --- a/DeeployTest/Platforms/MemPool/CMakeLists.txt +++ b/DeeployTest/Platforms/MemPool/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/MemPool/main.c b/DeeployTest/Platforms/MemPool/main.c index 5603bf2395..a0eda86c83 100644 --- a/DeeployTest/Platforms/MemPool/main.c +++ b/DeeployTest/Platforms/MemPool/main.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: main.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/DeeployTest/Platforms/PULPOpen/CMakeLists.txt b/DeeployTest/Platforms/PULPOpen/CMakeLists.txt index 6a0f685059..9dfd2f466f 100644 --- a/DeeployTest/Platforms/PULPOpen/CMakeLists.txt +++ b/DeeployTest/Platforms/PULPOpen/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/PULPOpen/inc/CycleCounter.h b/DeeployTest/Platforms/PULPOpen/inc/CycleCounter.h index 21d501e031..1bb48d7cb6 100644 --- a/DeeployTest/Platforms/PULPOpen/inc/CycleCounter.h +++ b/DeeployTest/Platforms/PULPOpen/inc/CycleCounter.h @@ -1,42 +1,22 @@ -/* ===================================================================== - * Title: CycleCounter.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef CYCLECOUNTER -#define CYCLECOUNTER - -// Resets the internal cycle counter to zero -void ResetTimer(void); - -// Starts the internal cycle counter -void StartTimer(void); - -// Stops the internal cycle counter -void StopTimer(void); - -// Returns the current number of cycles according to the internal cycle counter -unsigned int getCycles(void); - -#endif +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CYCLECOUNTER +#define CYCLECOUNTER + +// Resets the internal cycle counter to zero +void ResetTimer(void); + +// Starts the internal cycle counter +void StartTimer(void); + +// Stops the internal cycle counter +void StopTimer(void); + +// Returns the current number of cycles according to the internal cycle counter +unsigned int getCycles(void); + +#endif diff --git a/DeeployTest/Platforms/PULPOpen/src/CycleCounter.c b/DeeployTest/Platforms/PULPOpen/src/CycleCounter.c index 1f35d31891..e69af95d93 100644 --- a/DeeployTest/Platforms/PULPOpen/src/CycleCounter.c +++ b/DeeployTest/Platforms/PULPOpen/src/CycleCounter.c @@ -1,39 +1,19 @@ -/* ===================================================================== - * Title: CycleCounter.c - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "CycleCounter.h" -#include "pmsis.h" - -void ResetTimer() { - pi_perf_conf(PI_PERF_CYCLES); - pi_perf_cl_reset(); -} - -void StartTimer() { pi_perf_cl_start(); } - -void StopTimer() { pi_perf_cl_stop(); } - -unsigned int getCycles() { return pi_perf_cl_read(PI_PERF_CYCLES); } +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CycleCounter.h" +#include "pmsis.h" + +void ResetTimer() { + pi_perf_conf(PI_PERF_CYCLES); + pi_perf_cl_reset(); +} + +void StartTimer() { pi_perf_cl_start(); } + +void StopTimer() { pi_perf_cl_stop(); } + +unsigned int getCycles() { return pi_perf_cl_read(PI_PERF_CYCLES); } diff --git a/DeeployTest/Platforms/PULPOpen/src/deeploytest.c b/DeeployTest/Platforms/PULPOpen/src/deeploytest.c index 26457c3d8d..11d889e48d 100644 --- a/DeeployTest/Platforms/PULPOpen/src/deeploytest.c +++ b/DeeployTest/Platforms/PULPOpen/src/deeploytest.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: deeploytest.c - * Description: - * - * $Date: 26.12.2021 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "CycleCounter.h" diff --git a/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt b/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt index 1e618207f1..8c5dca824b 100644 --- a/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt +++ b/DeeployTest/Platforms/QEMU_ARM/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/QEMU_ARM/inc/CycleCounter.h b/DeeployTest/Platforms/QEMU_ARM/inc/CycleCounter.h index e9ca1c1801..5d679e0b11 100644 --- a/DeeployTest/Platforms/QEMU_ARM/inc/CycleCounter.h +++ b/DeeployTest/Platforms/QEMU_ARM/inc/CycleCounter.h @@ -1,46 +1,26 @@ -/* ===================================================================== - * Title: CycleCounter.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef CYCLECOUNTER -#define CYCLECOUNTER - -extern volatile unsigned int *DWT_CYCCNT; -extern volatile unsigned int *DWT_CONTROL; -extern volatile unsigned int *SCB_DEMCR; - -// Resets the internal cycle counter to zero -void ResetTimer(void); - -// Starts the internal cycle counter -void StartTimer(void); - -// Stops the internal cycle counter -void StopTimer(void); - -// Returns the current number of cycles according to the internal cycle counter -unsigned int getCycles(void); - -#endif +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CYCLECOUNTER +#define CYCLECOUNTER + +extern volatile unsigned int *DWT_CYCCNT; +extern volatile unsigned int *DWT_CONTROL; +extern volatile unsigned int *SCB_DEMCR; + +// Resets the internal cycle counter to zero +void ResetTimer(void); + +// Starts the internal cycle counter +void StartTimer(void); + +// Stops the internal cycle counter +void StopTimer(void); + +// Returns the current number of cycles according to the internal cycle counter +unsigned int getCycles(void); + +#endif diff --git a/DeeployTest/Platforms/QEMU_ARM/src/CycleCounter.c b/DeeployTest/Platforms/QEMU_ARM/src/CycleCounter.c index 3fbdc12b74..d522f6517d 100644 --- a/DeeployTest/Platforms/QEMU_ARM/src/CycleCounter.c +++ b/DeeployTest/Platforms/QEMU_ARM/src/CycleCounter.c @@ -1,64 +1,44 @@ -/* ===================================================================== - * Title: CycleCounter.c - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "CycleCounter.h" - -volatile unsigned int *DWT_CYCCNT = - (unsigned int *)0xE0001004; // address of the register -volatile unsigned int *DWT_CONTROL = - (unsigned int *)0xE0001000; // address of the register -volatile unsigned int *SCB_DEMCR = - (unsigned int *)0xE000EDFC; // address of the register - -static unsigned int prev_val = 0; -static int stopped = 0; - -void ResetTimer() { - - *SCB_DEMCR = *SCB_DEMCR | 0x01000000; - *DWT_CYCCNT = 0; // reset the counter - *DWT_CONTROL = 1; - stopped = 1; - prev_val = 0; -} - -void StartTimer() { - prev_val = *DWT_CYCCNT; - stopped = 0; -} - -void StopTimer() { - prev_val = *DWT_CYCCNT - prev_val; - stopped = 1; -} - -unsigned int getCycles() { - if (stopped) { - return prev_val; - } else { - return *DWT_CYCCNT - prev_val; - } -} +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CycleCounter.h" + +volatile unsigned int *DWT_CYCCNT = + (unsigned int *)0xE0001004; // address of the register +volatile unsigned int *DWT_CONTROL = + (unsigned int *)0xE0001000; // address of the register +volatile unsigned int *SCB_DEMCR = + (unsigned int *)0xE000EDFC; // address of the register + +static unsigned int prev_val = 0; +static int stopped = 0; + +void ResetTimer() { + + *SCB_DEMCR = *SCB_DEMCR | 0x01000000; + *DWT_CYCCNT = 0; // reset the counter + *DWT_CONTROL = 1; + stopped = 1; + prev_val = 0; +} + +void StartTimer() { + prev_val = *DWT_CYCCNT; + stopped = 0; +} + +void StopTimer() { + prev_val = *DWT_CYCCNT - prev_val; + stopped = 1; +} + +unsigned int getCycles() { + if (stopped) { + return prev_val; + } else { + return *DWT_CYCCNT - prev_val; + } +} diff --git a/DeeployTest/Platforms/QEMU_ARM/src/deeploytest.c b/DeeployTest/Platforms/QEMU_ARM/src/deeploytest.c index 0043941460..63ec1e1963 100644 --- a/DeeployTest/Platforms/QEMU_ARM/src/deeploytest.c +++ b/DeeployTest/Platforms/QEMU_ARM/src/deeploytest.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: deeploytest.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "Network.h" diff --git a/DeeployTest/Platforms/Siracusa/CMakeLists.txt b/DeeployTest/Platforms/Siracusa/CMakeLists.txt index 1e9cee730f..45e6191490 100644 --- a/DeeployTest/Platforms/Siracusa/CMakeLists.txt +++ b/DeeployTest/Platforms/Siracusa/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/Siracusa/inc/CycleCounter.h b/DeeployTest/Platforms/Siracusa/inc/CycleCounter.h index 21d501e031..1bb48d7cb6 100644 --- a/DeeployTest/Platforms/Siracusa/inc/CycleCounter.h +++ b/DeeployTest/Platforms/Siracusa/inc/CycleCounter.h @@ -1,42 +1,22 @@ -/* ===================================================================== - * Title: CycleCounter.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef CYCLECOUNTER -#define CYCLECOUNTER - -// Resets the internal cycle counter to zero -void ResetTimer(void); - -// Starts the internal cycle counter -void StartTimer(void); - -// Stops the internal cycle counter -void StopTimer(void); - -// Returns the current number of cycles according to the internal cycle counter -unsigned int getCycles(void); - -#endif +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CYCLECOUNTER +#define CYCLECOUNTER + +// Resets the internal cycle counter to zero +void ResetTimer(void); + +// Starts the internal cycle counter +void StartTimer(void); + +// Stops the internal cycle counter +void StopTimer(void); + +// Returns the current number of cycles according to the internal cycle counter +unsigned int getCycles(void); + +#endif diff --git a/DeeployTest/Platforms/Siracusa/src/CycleCounter.c b/DeeployTest/Platforms/Siracusa/src/CycleCounter.c index 1f35d31891..e69af95d93 100644 --- a/DeeployTest/Platforms/Siracusa/src/CycleCounter.c +++ b/DeeployTest/Platforms/Siracusa/src/CycleCounter.c @@ -1,39 +1,19 @@ -/* ===================================================================== - * Title: CycleCounter.c - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ -/* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "CycleCounter.h" -#include "pmsis.h" - -void ResetTimer() { - pi_perf_conf(PI_PERF_CYCLES); - pi_perf_cl_reset(); -} - -void StartTimer() { pi_perf_cl_start(); } - -void StopTimer() { pi_perf_cl_stop(); } - -unsigned int getCycles() { return pi_perf_cl_read(PI_PERF_CYCLES); } +/* + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CycleCounter.h" +#include "pmsis.h" + +void ResetTimer() { + pi_perf_conf(PI_PERF_CYCLES); + pi_perf_cl_reset(); +} + +void StartTimer() { pi_perf_cl_start(); } + +void StopTimer() { pi_perf_cl_stop(); } + +unsigned int getCycles() { return pi_perf_cl_read(PI_PERF_CYCLES); } diff --git a/DeeployTest/Platforms/Siracusa/src/deeploytest.c b/DeeployTest/Platforms/Siracusa/src/deeploytest.c index 26457c3d8d..11d889e48d 100644 --- a/DeeployTest/Platforms/Siracusa/src/deeploytest.c +++ b/DeeployTest/Platforms/Siracusa/src/deeploytest.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: deeploytest.c - * Description: - * - * $Date: 26.12.2021 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "CycleCounter.h" diff --git a/DeeployTest/Platforms/Snitch/CMakeLists.txt b/DeeployTest/Platforms/Snitch/CMakeLists.txt index 568303b08a..03a40258eb 100644 --- a/DeeployTest/Platforms/Snitch/CMakeLists.txt +++ b/DeeployTest/Platforms/Snitch/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/Snitch/main.c b/DeeployTest/Platforms/Snitch/main.c index b493fd52b9..89e6551436 100644 --- a/DeeployTest/Platforms/Snitch/main.c +++ b/DeeployTest/Platforms/Snitch/main.c @@ -1,28 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * - * File: deeploytest.c - * - * Last edited: 23.04.2024 - * - * Copyright (C) 2024, ETH Zurich and University of Bologna. - * - * Author: Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "CycleCounter.h" diff --git a/DeeployTest/Platforms/SoftHier/CMakeLists.txt b/DeeployTest/Platforms/SoftHier/CMakeLists.txt index 20797bed05..413136a533 100644 --- a/DeeployTest/Platforms/SoftHier/CMakeLists.txt +++ b/DeeployTest/Platforms/SoftHier/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(ProjectId ${TESTNAME}) diff --git a/DeeployTest/Platforms/SoftHier/main.c b/DeeployTest/Platforms/SoftHier/main.c index 86eb31f712..157c048159 100644 --- a/DeeployTest/Platforms/SoftHier/main.c +++ b/DeeployTest/Platforms/SoftHier/main.c @@ -1,28 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * File: main.c - * - * Last edited: 26.05.2025 - * - * Copyright (C) 2025, ETH Zurich and University of Bologna. - * - * Author: Bowen Wang (bowwang@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/DeeployTest/deeployStateEqualityTest.py b/DeeployTest/deeployStateEqualityTest.py index 58dbc7dad4..6a3f5cdebe 100644 --- a/DeeployTest/deeployStateEqualityTest.py +++ b/DeeployTest/deeployStateEqualityTest.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: deeployStateEqualityTest.py -# -# Last edited: 04.05.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import argparse import copy diff --git a/DeeployTest/generateNetwork.py b/DeeployTest/generateNetwork.py index 7e05260c35..1aebd4a826 100644 --- a/DeeployTest/generateNetwork.py +++ b/DeeployTest/generateNetwork.py @@ -1,29 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: generateNetwork.py -# -# Last edited: 08.01.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: -# - Moritz Scherer, ETH Zurich -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os import sys diff --git a/DeeployTest/profiling2csv.py b/DeeployTest/profiling2csv.py index 7d8feb5950..da080c07d4 100644 --- a/DeeployTest/profiling2csv.py +++ b/DeeployTest/profiling2csv.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: profiling2csv.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import argparse import csv diff --git a/DeeployTest/testComponentGraph.py b/DeeployTest/testComponentGraph.py index e091e0b419..7875074092 100644 --- a/DeeployTest/testComponentGraph.py +++ b/DeeployTest/testComponentGraph.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testComponentGraph.py -# -# Last edited: 10.10.2023. -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testDebugPrintPass.py b/DeeployTest/testDebugPrintPass.py index a3e05e39e0..6cd0e9f037 100644 --- a/DeeployTest/testDebugPrintPass.py +++ b/DeeployTest/testDebugPrintPass.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: testDebugPrinting.py -# -# Last edited: 14.05.2024. -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testDmas.py b/DeeployTest/testDmas.py index c014b7676b..df6926b48d 100644 --- a/DeeployTest/testDmas.py +++ b/DeeployTest/testDmas.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: testDmas.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import itertools import subprocess diff --git a/DeeployTest/testEngineAwareOptimizerWrapper.py b/DeeployTest/testEngineAwareOptimizerWrapper.py index 877230bc75..81c2d30d27 100644 --- a/DeeployTest/testEngineAwareOptimizerWrapper.py +++ b/DeeployTest/testEngineAwareOptimizerWrapper.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testEngineAwareOptimizerWrapper.py -# -# Last edited: 10.10.2023. -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index ecca6266c9..0714f78d7e 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testMVP.py -# -# Last edited: 31.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os import sys diff --git a/DeeployTest/testMemoryLevelExtension.py b/DeeployTest/testMemoryLevelExtension.py index 22a5405a5c..0e1ed6cc43 100644 --- a/DeeployTest/testMemoryLevelExtension.py +++ b/DeeployTest/testMemoryLevelExtension.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: testMemoryLevelExtension.py -# -# Last edited: 04.05.2022 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import copy import os diff --git a/DeeployTest/testPrintInputOutputTransformation.py b/DeeployTest/testPrintInputOutputTransformation.py index 1bf4f90c54..c8f0ee70fe 100644 --- a/DeeployTest/testPrintInputOutputTransformation.py +++ b/DeeployTest/testPrintInputOutputTransformation.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: testPrintInputOutputTransformation.py -# -# Last edited: 15.05.2024. -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testRegexMatching.py b/DeeployTest/testRegexMatching.py index 45ecd5134d..ec91a01e97 100644 --- a/DeeployTest/testRegexMatching.py +++ b/DeeployTest/testRegexMatching.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRegexMatching.py -# -# Last edited: 10.10.2023. -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re diff --git a/DeeployTest/testReplaceInsertSubgraph.py b/DeeployTest/testReplaceInsertSubgraph.py index c6a8aa53b2..c3129fff76 100644 --- a/DeeployTest/testReplaceInsertSubgraph.py +++ b/DeeployTest/testReplaceInsertSubgraph.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testReplaceInsertSubgraph.py -# -# Last edited: 10.10.2023. -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testRunner_chimera.py b/DeeployTest/testRunner_chimera.py index 82a94ad815..d3a7093a72 100644 --- a/DeeployTest/testRunner_chimera.py +++ b/DeeployTest/testRunner_chimera.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_chimera.py -# -# Last edited: 16.06.2025 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Victor Jung, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_cortexm.py b/DeeployTest/testRunner_cortexm.py index efa927fd91..64d6246b74 100644 --- a/DeeployTest/testRunner_cortexm.py +++ b/DeeployTest/testRunner_cortexm.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: testRunner_qemu.py -# -# Last edited: 17.03.2023 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_generic.py b/DeeployTest/testRunner_generic.py index 70909bf7e1..496b1db394 100644 --- a/DeeployTest/testRunner_generic.py +++ b/DeeployTest/testRunner_generic.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_generic.py -# -# Last edited: 17.03.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_mempool.py b/DeeployTest/testRunner_mempool.py index c3bbd4f0c7..919603f454 100644 --- a/DeeployTest/testRunner_mempool.py +++ b/DeeployTest/testRunner_mempool.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: testRunner_mempool.py -# -# Last edited: 17.03.2023 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_siracusa.py b/DeeployTest/testRunner_siracusa.py index 43e10de8d9..b83046de55 100644 --- a/DeeployTest/testRunner_siracusa.py +++ b/DeeployTest/testRunner_siracusa.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_siracusa.py -# -# Last edited: 11.04.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_siracusa_l3dma.py b/DeeployTest/testRunner_siracusa_l3dma.py index f174cdd867..b70d8dda22 100644 --- a/DeeployTest/testRunner_siracusa_l3dma.py +++ b/DeeployTest/testRunner_siracusa_l3dma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: testRunner_siracusa_l3dma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testRunner_siracusa_mchandma.py b/DeeployTest/testRunner_siracusa_mchandma.py index 8fe5fe6e9e..56ed6f5a14 100644 --- a/DeeployTest/testRunner_siracusa_mchandma.py +++ b/DeeployTest/testRunner_siracusa_mchandma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: testRunner_siracusa_mchandma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testRunner_snitch.py b/DeeployTest/testRunner_snitch.py index a84d072a33..42a7353818 100644 --- a/DeeployTest/testRunner_snitch.py +++ b/DeeployTest/testRunner_snitch.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: testRunner_snitch.py -# -# Last edited: 11.08.2025 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Authors: -# - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_snitch_dma.py b/DeeployTest/testRunner_snitch_dma.py index 9fa432a6f4..80073ac5ed 100644 --- a/DeeployTest/testRunner_snitch_dma.py +++ b/DeeployTest/testRunner_snitch_dma.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: testRunner_snitch_dma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os diff --git a/DeeployTest/testRunner_softhier.py b/DeeployTest/testRunner_softhier.py index bc71d7a7cd..9350dce4cf 100644 --- a/DeeployTest/testRunner_softhier.py +++ b/DeeployTest/testRunner_softhier.py @@ -1,25 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: testRunner_softhier.py -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: Bowen Wang , ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_tiled_siracusa.py b/DeeployTest/testRunner_tiled_siracusa.py index cea732f3d5..7bf08b7b28 100644 --- a/DeeployTest/testRunner_tiled_siracusa.py +++ b/DeeployTest/testRunner_tiled_siracusa.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_tiled_siracusa.py -# -# Last edited: 31.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_tiled_siracusa_w_neureka.py b/DeeployTest/testRunner_tiled_siracusa_w_neureka.py index fef043b7ac..435f32b895 100644 --- a/DeeployTest/testRunner_tiled_siracusa_w_neureka.py +++ b/DeeployTest/testRunner_tiled_siracusa_w_neureka.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_tiled_siracusa_w_neureka.py -# -# Last edited: 31.10.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testRunner_tiled_snitch.py b/DeeployTest/testRunner_tiled_snitch.py index 3c2f4d9bda..7787d1f844 100644 --- a/DeeployTest/testRunner_tiled_snitch.py +++ b/DeeployTest/testRunner_tiled_snitch.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testRunner_tiled_snitch.py -# -# Last edited: 23.04.2024 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from testUtils.testRunner import TestRunner, TestRunnerArgumentParser diff --git a/DeeployTest/testSchedulingExtension.py b/DeeployTest/testSchedulingExtension.py index bd339b93dd..be77ecce53 100644 --- a/DeeployTest/testSchedulingExtension.py +++ b/DeeployTest/testSchedulingExtension.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: tilerExtensionTest.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os from collections import OrderedDict diff --git a/DeeployTest/testSlice_PULP.py b/DeeployTest/testSlice_PULP.py index 35052381ee..0dbda95840 100644 --- a/DeeployTest/testSlice_PULP.py +++ b/DeeployTest/testSlice_PULP.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testSlice_PULP.py -# -# Last edited: 15.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import argparse import os diff --git a/DeeployTest/testTilerExtension.py b/DeeployTest/testTilerExtension.py index 6ee23b40fc..e42a06d774 100644 --- a/DeeployTest/testTilerExtension.py +++ b/DeeployTest/testTilerExtension.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: tilerExtensionTest.py -# -# Last edited: 09.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os from collections import OrderedDict diff --git a/DeeployTest/testTypes.py b/DeeployTest/testTypes.py index 957a1f6274..9858015229 100644 --- a/DeeployTest/testTypes.py +++ b/DeeployTest/testTypes.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: testTypes.py -# -# Last edited: 15.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import pickle diff --git a/DeeployTest/testUtils/ProfilingTraceParser.py b/DeeployTest/testUtils/ProfilingTraceParser.py index 3374c88fec..398c1e57d0 100644 --- a/DeeployTest/testUtils/ProfilingTraceParser.py +++ b/DeeployTest/testUtils/ProfilingTraceParser.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: ProfilingTraceParser.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re from dataclasses import dataclass diff --git a/DeeployTest/testUtils/__init__.py b/DeeployTest/testUtils/__init__.py index 65ec809815..be436b64a3 100644 --- a/DeeployTest/testUtils/__init__.py +++ b/DeeployTest/testUtils/__init__.py @@ -1,26 +1,5 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: __init__.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from . import * diff --git a/DeeployTest/testUtils/codeGenerate.py b/DeeployTest/testUtils/codeGenerate.py index c873e447ca..8addf6827b 100644 --- a/DeeployTest/testUtils/codeGenerate.py +++ b/DeeployTest/testUtils/codeGenerate.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: codeGenerate.py -# -# Last edited: 23.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os from typing import List, Tuple diff --git a/DeeployTest/testUtils/dmaUtils.py b/DeeployTest/testUtils/dmaUtils.py index 6b476ffb17..3266ce5129 100644 --- a/DeeployTest/testUtils/dmaUtils.py +++ b/DeeployTest/testUtils/dmaUtils.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: dmaUtils.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import math from typing import Dict, List, Optional, Tuple, Type diff --git a/DeeployTest/testUtils/graphColoring.py b/DeeployTest/testUtils/graphColoring.py index 4437c947ea..d703d81862 100644 --- a/DeeployTest/testUtils/graphColoring.py +++ b/DeeployTest/testUtils/graphColoring.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: graphColoring.py -# -# Last edited: 10.10.2023. -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, University of Bologna -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Union diff --git a/DeeployTest/testUtils/graphDebug.py b/DeeployTest/testUtils/graphDebug.py index 9aa87d9efd..676fdca56a 100644 --- a/DeeployTest/testUtils/graphDebug.py +++ b/DeeployTest/testUtils/graphDebug.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: graphDebug.py -# -# Last edited: 23.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Dict, Tuple diff --git a/DeeployTest/testUtils/graphDiffUtils.py b/DeeployTest/testUtils/graphDiffUtils.py index a3b4d48516..c89e799582 100644 --- a/DeeployTest/testUtils/graphDiffUtils.py +++ b/DeeployTest/testUtils/graphDiffUtils.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: graphDiffUtils.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/DeeployTest/testUtils/platformMapping.py b/DeeployTest/testUtils/platformMapping.py index 56cd3d7d28..48c5777905 100644 --- a/DeeployTest/testUtils/platformMapping.py +++ b/DeeployTest/testUtils/platformMapping.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: platformMapping.py -# -# Last edited: 23.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Callable, Dict, Optional, Tuple, Type, Union diff --git a/DeeployTest/testUtils/testRunner.py b/DeeployTest/testUtils/testRunner.py index 353856c2ca..1d274511e2 100644 --- a/DeeployTest/testUtils/testRunner.py +++ b/DeeployTest/testUtils/testRunner.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna # -# File: testRunner.py -# -# Last edited: 17.03.2023 -# -# Copyright (C) 2022, ETH Zurich and University of Bologna. -# -# Author: Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import argparse import codecs diff --git a/DeeployTest/testUtils/tilingUtils.py b/DeeployTest/testUtils/tilingUtils.py index a25a50938d..0c3986cd6e 100644 --- a/DeeployTest/testUtils/tilingUtils.py +++ b/DeeployTest/testUtils/tilingUtils.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: tilingUtils.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Moirtz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import List, Union diff --git a/DeeployTest/testUtils/typeMapping.py b/DeeployTest/testUtils/typeMapping.py index 15242c93ea..232fd1e274 100644 --- a/DeeployTest/testUtils/typeMapping.py +++ b/DeeployTest/testUtils/typeMapping.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: typeMapping.py -# -# Last edited: 22.05.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from typing import Tuple, Type diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 0b4f59accb..0000000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2022 deeploy - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 0000000000..137069b823 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/CC-BY-ND-4.0.txt b/LICENSES/CC-BY-ND-4.0.txt new file mode 100644 index 0000000000..09a21c7358 --- /dev/null +++ b/LICENSES/CC-BY-ND-4.0.txt @@ -0,0 +1,154 @@ +Creative Commons Attribution-NoDerivatives 4.0 International + + Creative Commons Corporation (“Creative Commonsâ€) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is†basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. + +Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors. + +Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public. + +Creative Commons Attribution-NoDerivatives 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. + +Section 1 – Definitions. + + a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. + + b. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + + c. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. + + d. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. + + e. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. + + f. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. + + g. Licensor means the individual(s) or entity(ies) granting rights under this Public License. + + h. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. + + i. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. + + j. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce and reproduce, but not Share, Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + + 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. + + 5. Downstream recipients. + + A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. + + B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + + 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this Public License. + + 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material, You must: + + A. retain the following if it is supplied by the Licensor with the Licensed Material: + + i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + + C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. + + 2. For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material. + + 3. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. + + 4. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database, provided You do not Share Adapted Material; + + b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + + a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. + + b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. + + c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + + a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + + c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. + + d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. + +Section 8 – Interpretation. + + a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. + + c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. + + d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.†Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons†or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000000..d817195dad --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 0ff8de1805..fb9a9a302a 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna # -# File: Makefile -# -# Created: 30.06.2023 -# -# Copyright (C) 2023, ETH Zurich and University of Bologna. -# -# Authors: -# - Moritz Scherer, ETH Zurich -# - Victor Jung, ETH Zurich -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. SHELL = /usr/bin/env bash ROOT_DIR := $(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) @@ -568,60 +544,27 @@ chimera-sdk: ${CHIMERA_SDK_INSTALL_DIR} format: @echo "Formatting all relevant files..." @echo " - Format Python Files" - @yapf -ipr -e "third_party/" -e "install/" -e "toolchain/" . + @yapf -ipr -e "*/TEST_*/" -e "*/third_party/" -e "install/" -e "toolchain/" . @echo " - Format Python Imports" - @isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ + @isort --quiet --sg "**/TEST_*/*" --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ @autoflake -i -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . @echo " - Format C/C++ Files" - @python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format -ir ./ scripts + @python scripts/run_clang_format.py -e "*/TEST_*/*" -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format -ir ./ scripts -lint: check-licenses +lint: @echo "Linting all relevant files..." + @echo " - Lint License Headers" + @scripts/reuse_skip_wrapper.py $$(git ls-files '*.py' '*.c' '*.h' '*.html' '*.rst' '*.yml' '*.yaml') @echo " - Lint Python Files" - @yapf -rpd -e "third_party/" -e "install/" -e "toolchain/" . + @yapf -rpd -e "*/TEST_*/" -e "*/third_party/" -e "install/" -e "toolchain/" . @echo " - Lint Python Imports" - @isort --quiet --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c + @isort --quiet --sg "**/TEST_*/*" --sg "**/third_party/*" --sg "install/*" --sg "toolchain/*" ./ -c @autoflake --quiet -c -r --remove-all-unused-imports --ignore-init-module-imports --exclude "**/third_party/*,**/install/*,**/toolchain/*" . @echo " - Lint C/C++ Files" - @python scripts/run_clang_format.py -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts + @python scripts/run_clang_format.py -e "*/TEST_*/*" -e "*/third_party/*" -e "*/install/*" -e "*/toolchain/*" -r --clang-format-executable=${LLVM_INSTALL_DIR}/bin/clang-format . scripts @echo " - Lint YAML files" @yamllint . -check-licenses: - @echo "Checking SPDX license headers in all relevant files..." - @rc=0; \ - echo " - Check Python Files"; \ - missing_py=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.py" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude "run_clang_format.py" . || true); \ - if [ -n "$$missing_py" ]; then echo "$$missing_py"; rc=1; fi; \ - echo " - Check C Files"; \ - missing_c=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.c" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true); \ - if [ -n "$$missing_c" ]; then echo "$$missing_c"; rc=1; fi; \ - echo " - Check C Header Files"; \ - missing_h=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.h" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true); \ - if [ -n "$$missing_h" ]; then echo "$$missing_h"; rc=1; fi; \ - echo " - Check YAML Files"; \ - missing_yaml=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.yaml" --include="*.yml" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true); \ - if [ -n "$$missing_yaml" ]; then echo "$$missing_yaml"; rc=1; fi; \ - echo " - Check CMake Files"; \ - missing_cmake=$$(grep -Lr "SPDX-License-Identifier: Apache-2.0" --include="*.cmake" --include="CMakeLists.txt" \ - --exclude-dir="toolchain" --exclude-dir="install" --exclude-dir=".git" \ - --exclude-dir="third_party" --exclude-dir="TEST_*" --exclude-dir="TestFiles" \ - --exclude-dir="runtime" . || true); \ - if [ -n "$$missing_cmake" ]; then echo "$$missing_cmake"; rc=1; fi; \ - exit $$rc - docs: make -C docs html diff --git a/README.md b/README.md index 22b1ccd45d..d27b935b2f 100644 --- a/README.md +++ b/README.md @@ -126,5 +126,9 @@ The preprint is available on arXiv @ [arXiv:2408.04413](https://arxiv.org/abs/24 The preprint is available on arXiv @ [arXiv:2408.02473](https://arxiv.org/abs/2408.02473). ## License +All licenses used in this repository are listed under the `LICENSES` folder. Unless specified otherwise in the respective file headers, all code checked into this repository is made available under a permissive license. +- Most software sources and tool scripts are licensed under the [Apache 2.0 license](https://opensource.org/licenses/Apache-2.0). +- Some files in the `scripts` directory are licensed under the [MIT license](https://opensource.org/license/mit). +- Markdown, JSON, text files, pictures, and files in the `DeeployTest/Tests` directory are licensed under the [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0) license (CC BY 4.0). -Unless specified otherwise in the respective file headers, all code checked into this repository is made available under a permissive license. All software sources and tool scripts are licensed under Apache 2.0, except for files contained in the `scripts` directory, which are licensed under the MIT license, and files contained in the `DeeployTest/Tests`directory, which are licensed under the [Creative Commons Attribution-NoDerivates 4.0 International](https://creativecommons.org/licenses/by-nd/4.0) license (CC BY-ND 4.0). \ No newline at end of file +To extract license information for all files, you can use the [reuse tool](https://reuse.software/) and by running `reuse spdx` in the root directory of this repository. \ No newline at end of file diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000000..b37b8dfee0 --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,36 @@ +version = 1 + +[[annotations]] +path = "DeeployTest/Tests/**" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = "docs/_static/**" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = "**/*.md" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = "**/*.txt" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = "**/*.patch" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = "*.json" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" + +[[annotations]] +path = ".vscode/*.json" +SPDX-FileCopyrightText = "2023 ETH Zurich and University of Bologna" +SPDX-License-Identifier = "CC-BY-ND-4.0" \ No newline at end of file diff --git a/TargetLibraries/CMSIS/CMakeLists.txt b/TargetLibraries/CMSIS/CMakeLists.txt index 1cd382d8ef..03f04ffe09 100644 --- a/TargetLibraries/CMSIS/CMakeLists.txt +++ b/TargetLibraries/CMSIS/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/CMSIS/inc/DeeployMath.h b/TargetLibraries/CMSIS/inc/DeeployMath.h index 7aa1b1805c..a40ad3345d 100644 --- a/TargetLibraries/CMSIS/inc/DeeployMath.h +++ b/TargetLibraries/CMSIS/inc/DeeployMath.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: DeeployMath.h - * Description: - * - * $Date: 30.12.2021 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/CMSIS/src/Util.c b/TargetLibraries/CMSIS/src/Util.c index 257ea9590a..a48c969b71 100644 --- a/TargetLibraries/CMSIS/src/Util.c +++ b/TargetLibraries/CMSIS/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/Chimera/CMakeLists.txt b/TargetLibraries/Chimera/CMakeLists.txt index ba37adb955..f69a741a85 100644 --- a/TargetLibraries/Chimera/CMakeLists.txt +++ b/TargetLibraries/Chimera/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/Chimera/inc/DeeployChimeraMath.h b/TargetLibraries/Chimera/inc/DeeployChimeraMath.h index b4bbf0b0b8..756b532850 100644 --- a/TargetLibraries/Chimera/inc/DeeployChimeraMath.h +++ b/TargetLibraries/Chimera/inc/DeeployChimeraMath.h @@ -1,9 +1,7 @@ /* - * Copyright 2025 ETH Zurich. - * Licensed under the Apache License, Version 2.0, see LICENSE for details. - * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * Victor Jung + * SPDX-License-Identifier: Apache-2.0 */ #ifndef __DEEPLOY_CHIMERA_MATH_HEADER_ diff --git a/TargetLibraries/Chimera/src/Add.c b/TargetLibraries/Chimera/src/Add.c index d4bab85258..b90c517fff 100644 --- a/TargetLibraries/Chimera/src/Add.c +++ b/TargetLibraries/Chimera/src/Add.c @@ -1,9 +1,7 @@ /* - * Copyright 2025 ETH Zurich. - * Licensed under the Apache License, Version 2.0, see LICENSE for details. - * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * Victor Jung + * SPDX-License-Identifier: Apache-2.0 */ #include "DeeployChimeraMath.h" diff --git a/TargetLibraries/Generic/CMakeLists.txt b/TargetLibraries/Generic/CMakeLists.txt index 8cdb36f2cf..b129c1c994 100644 --- a/TargetLibraries/Generic/CMakeLists.txt +++ b/TargetLibraries/Generic/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/Generic/inc/DeeployBasicMath.h b/TargetLibraries/Generic/inc/DeeployBasicMath.h index 7f123e9dfc..f647c833e0 100644 --- a/TargetLibraries/Generic/inc/DeeployBasicMath.h +++ b/TargetLibraries/Generic/inc/DeeployBasicMath.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: DeeployBasicMath.h - * Description: - * - * Date: 14.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich - * - Victor Jung, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Convolution.h b/TargetLibraries/Generic/inc/kernel/Convolution.h index b1ee40039b..f86e8dcd75 100644 --- a/TargetLibraries/Generic/inc/kernel/Convolution.h +++ b/TargetLibraries/Generic/inc/kernel/Convolution.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Convolution.h - * Description: - * - * Date: 12.05.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich - * - Calin Diaconu, University of Bologna + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_CONVOLUTION_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/DWConvolution.h b/TargetLibraries/Generic/inc/kernel/DWConvolution.h index 23c8447928..b1b17e6c24 100644 --- a/TargetLibraries/Generic/inc/kernel/DWConvolution.h +++ b/TargetLibraries/Generic/inc/kernel/DWConvolution.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: DWConvolution.h - * Description: - * - * Date: 05.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich - * - Calin Diaconu, University of Bologna + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_DWCONVOLUTION_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Div.h b/TargetLibraries/Generic/inc/kernel/Div.h index 4929936667..7e3706db73 100644 --- a/TargetLibraries/Generic/inc/kernel/Div.h +++ b/TargetLibraries/Generic/inc/kernel/Div.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Div.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_DIV_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/GELU.h b/TargetLibraries/Generic/inc/kernel/GELU.h index 702c1c09cc..f7e56e3beb 100644 --- a/TargetLibraries/Generic/inc/kernel/GELU.h +++ b/TargetLibraries/Generic/inc/kernel/GELU.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: GELU.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_GELU_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Gemm.h b/TargetLibraries/Generic/inc/kernel/Gemm.h index 19e424f6c4..0472c51cfc 100644 --- a/TargetLibraries/Generic/inc/kernel/Gemm.h +++ b/TargetLibraries/Generic/inc/kernel/Gemm.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Gemm.h - * Description: - * - * Date: 05.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_GEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Hardswish.h b/TargetLibraries/Generic/inc/kernel/Hardswish.h index 8e2e06f923..e0df42efbb 100644 --- a/TargetLibraries/Generic/inc/kernel/Hardswish.h +++ b/TargetLibraries/Generic/inc/kernel/Hardswish.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Hardswish.h -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_BASIC_MATH_HARDSWISH_KERNEL_HEADER_ #define __DEEPLOY_BASIC_MATH_HARDSWISH_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Layernorm.h b/TargetLibraries/Generic/inc/kernel/Layernorm.h index 5518a47d72..3ca4f1d0c5 100644 --- a/TargetLibraries/Generic/inc/kernel/Layernorm.h +++ b/TargetLibraries/Generic/inc/kernel/Layernorm.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Layernorm.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_LAYERNORM_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/MatMul.h b/TargetLibraries/Generic/inc/kernel/MatMul.h index 2b75267893..adf1d8459e 100644 --- a/TargetLibraries/Generic/inc/kernel/MatMul.h +++ b/TargetLibraries/Generic/inc/kernel/MatMul.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: MatMul.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_MATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/MaxPool.h b/TargetLibraries/Generic/inc/kernel/MaxPool.h index bedffbf269..585b4967fc 100644 --- a/TargetLibraries/Generic/inc/kernel/MaxPool.h +++ b/TargetLibraries/Generic/inc/kernel/MaxPool.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool.h - * Description: - * - * Date: 04.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_MAXPOOL_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/RMSNorm.h b/TargetLibraries/Generic/inc/kernel/RMSNorm.h index a960b4a21c..576f10cf5e 100644 --- a/TargetLibraries/Generic/inc/kernel/RMSNorm.h +++ b/TargetLibraries/Generic/inc/kernel/RMSNorm.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: RMSNorm.h - * Description: - * - * $Date: 20.02.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_RMSNORM_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/RQDiv.h b/TargetLibraries/Generic/inc/kernel/RQDiv.h index 3e79d01a7e..69bcc12dd4 100644 --- a/TargetLibraries/Generic/inc/kernel/RQDiv.h +++ b/TargetLibraries/Generic/inc/kernel/RQDiv.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: RQDiv.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_RQDIV_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/RQGELU.h b/TargetLibraries/Generic/inc/kernel/RQGELU.h index 8965a34f8c..3c866950e9 100644 --- a/TargetLibraries/Generic/inc/kernel/RQGELU.h +++ b/TargetLibraries/Generic/inc/kernel/RQGELU.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: RQGELU.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_RQGELU_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/RQHardswish.h b/TargetLibraries/Generic/inc/kernel/RQHardswish.h index b66c03d789..672d312811 100644 --- a/TargetLibraries/Generic/inc/kernel/RQHardswish.h +++ b/TargetLibraries/Generic/inc/kernel/RQHardswish.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: RQHardswish.h -# -# Last edited: 23.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_BASIC_MATH_RQIHARDSWISH_KERNEL_HEADER_ #define __DEEPLOY_BASIC_MATH_RQIHARDSWISH_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Relu.h b/TargetLibraries/Generic/inc/kernel/Relu.h index 535ee4d4d0..02e62df95c 100644 --- a/TargetLibraries/Generic/inc/kernel/Relu.h +++ b/TargetLibraries/Generic/inc/kernel/Relu.h @@ -1,31 +1,7 @@ - -/* ===================================================================== - * Title: Relu.h - * Description: - * - * Date: 23.1.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_RELU_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/RequantShift.h b/TargetLibraries/Generic/inc/kernel/RequantShift.h index cc1c1cd36c..fe550fac76 100644 --- a/TargetLibraries/Generic/inc/kernel/RequantShift.h +++ b/TargetLibraries/Generic/inc/kernel/RequantShift.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: RequantShift.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_REQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/Softmax.h b/TargetLibraries/Generic/inc/kernel/Softmax.h index 56a46f6e0b..e5e817d218 100644 --- a/TargetLibraries/Generic/inc/kernel/Softmax.h +++ b/TargetLibraries/Generic/inc/kernel/Softmax.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Softmax.h - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_SOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/macros.h b/TargetLibraries/Generic/inc/macros.h index bbf7a01f8f..d97cfecb7c 100644 --- a/TargetLibraries/Generic/inc/macros.h +++ b/TargetLibraries/Generic/inc/macros.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: macros.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_MACROS_HEADER_ diff --git a/TargetLibraries/Generic/inc/types.h b/TargetLibraries/Generic/inc/types.h index 60ed361307..be75317984 100644 --- a/TargetLibraries/Generic/inc/types.h +++ b/TargetLibraries/Generic/inc/types.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: types.h - * Description: - * - * Date: 11.11.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2024 ETH Zurich and University of Bologna. - * - * Authors: - * - Francesco Conti, University of Bologna + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_TYPES_HEADER_ diff --git a/TargetLibraries/Generic/inc/utils.h b/TargetLibraries/Generic/inc/utils.h index 53aad633b7..f64642908e 100644 --- a/TargetLibraries/Generic/inc/utils.h +++ b/TargetLibraries/Generic/inc/utils.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: utils.h - * Description: - * - * Date: 06.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_UTIL_HEADER_ diff --git a/TargetLibraries/Generic/src/Convolution_fp32.c b/TargetLibraries/Generic/src/Convolution_fp32.c index 313f2f47e3..172749bce2 100644 --- a/TargetLibraries/Generic/src/Convolution_fp32.c +++ b/TargetLibraries/Generic/src/Convolution_fp32.c @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Convolution_float32.c - * Description: Float32 version of Conv2D with NCHW format (pre-padded input) - * - * Date: 12.05.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich - * - Calin Diaconu, University of Bologna + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Convolution_s8.c b/TargetLibraries/Generic/src/Convolution_s8.c index a250124a5e..c5c2ffecfa 100644 --- a/TargetLibraries/Generic/src/Convolution_s8.c +++ b/TargetLibraries/Generic/src/Convolution_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Convolution_s8.c - * Description: - * - * Date: 04.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/DWConvolution_fp32.c b/TargetLibraries/Generic/src/DWConvolution_fp32.c index 355433d427..b9b5f0b638 100644 --- a/TargetLibraries/Generic/src/DWConvolution_fp32.c +++ b/TargetLibraries/Generic/src/DWConvolution_fp32.c @@ -1,27 +1,7 @@ -/* ===================================================================== - * Title: DWConvolution_float32.c - * Description: Float32 version of Conv2D with NCHW format (pre-padded input) - * - * Date: 12.05.2025 - * - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Authors: - * - Calin Diaconu, University of Bologna +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/DWConvolution_s8.c b/TargetLibraries/Generic/src/DWConvolution_s8.c index 1a7da6aa1d..bf3736fdbd 100644 --- a/TargetLibraries/Generic/src/DWConvolution_s8.c +++ b/TargetLibraries/Generic/src/DWConvolution_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: DWConvolution_s8.c - * Description: - * - * Date: 05.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Div_fp32.c b/TargetLibraries/Generic/src/Div_fp32.c index c8f93dae0d..77214e5b84 100644 --- a/TargetLibraries/Generic/src/Div_fp32.c +++ b/TargetLibraries/Generic/src/Div_fp32.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: Div_fp32.c - * Description: - * - * $Date: 23.01.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Div_s32.c b/TargetLibraries/Generic/src/Div_s32.c index c2b66ad3f3..f3bb65b6ba 100644 --- a/TargetLibraries/Generic/src/Div_s32.c +++ b/TargetLibraries/Generic/src/Div_s32.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Div_s32.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/GELU_fp32.c b/TargetLibraries/Generic/src/GELU_fp32.c index 880d715fc6..9dbf15c4a3 100644 --- a/TargetLibraries/Generic/src/GELU_fp32.c +++ b/TargetLibraries/Generic/src/GELU_fp32.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: GELU_fp32.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/GELU_s8.c b/TargetLibraries/Generic/src/GELU_s8.c index 91f42546e6..d9940e9553 100644 --- a/TargetLibraries/Generic/src/GELU_s8.c +++ b/TargetLibraries/Generic/src/GELU_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: GELU_s8.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Gemm_fp32.c b/TargetLibraries/Generic/src/Gemm_fp32.c index 512969c100..a3c6418508 100644 --- a/TargetLibraries/Generic/src/Gemm_fp32.c +++ b/TargetLibraries/Generic/src/Gemm_fp32.c @@ -1,31 +1,9 @@ -/* ===================================================================== - * Title: GEMM_fp32.c - * Description: - * - * Date: 24.01.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ + #include "DeeployBasicMath.h" void Gemm_fp32_fp32_fp32_fp32(const float32_t *__restrict__ pSrcA, diff --git a/TargetLibraries/Generic/src/Gemm_s8.c b/TargetLibraries/Generic/src/Gemm_s8.c index bd5e807797..8d53e21f2e 100644 --- a/TargetLibraries/Generic/src/Gemm_s8.c +++ b/TargetLibraries/Generic/src/Gemm_s8.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: Gemm_s8.c - * Description: - * - * $Date: 05.01.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Hardswish_s8.c b/TargetLibraries/Generic/src/Hardswish_s8.c index fb7c1f9213..384e49c98d 100644 --- a/TargetLibraries/Generic/src/Hardswish_s8.c +++ b/TargetLibraries/Generic/src/Hardswish_s8.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Hardswish_s8.c -# -# Last edited: 22.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Layernorm_fp32.c b/TargetLibraries/Generic/src/Layernorm_fp32.c index 2def4fcb4f..f5337f6154 100644 --- a/TargetLibraries/Generic/src/Layernorm_fp32.c +++ b/TargetLibraries/Generic/src/Layernorm_fp32.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: Layernorm_fp32.c - * Description: - * - * $Date: 22.01.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Layernorm_s8.c b/TargetLibraries/Generic/src/Layernorm_s8.c index a7079a9f8a..281cef9d0c 100644 --- a/TargetLibraries/Generic/src/Layernorm_s8.c +++ b/TargetLibraries/Generic/src/Layernorm_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Layernorm_s8.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/MatMul_fp32.c b/TargetLibraries/Generic/src/MatMul_fp32.c index f7df3e5321..d8226d8fa8 100644 --- a/TargetLibraries/Generic/src/MatMul_fp32.c +++ b/TargetLibraries/Generic/src/MatMul_fp32.c @@ -1,31 +1,9 @@ -/* ===================================================================== - * Title: GEMM_fp32.c - * Description: - * - * Date: 24.01.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ + #include "DeeployBasicMath.h" void MatMul_fp32_fp32_fp32(const float32_t *__restrict__ pSrcA, diff --git a/TargetLibraries/Generic/src/MatMul_s8.c b/TargetLibraries/Generic/src/MatMul_s8.c index 2b53baa391..20e98b6da5 100644 --- a/TargetLibraries/Generic/src/MatMul_s8.c +++ b/TargetLibraries/Generic/src/MatMul_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s8.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/MaxPool_fp32.c b/TargetLibraries/Generic/src/MaxPool_fp32.c index 82211a4bb7..407f32c8f6 100644 --- a/TargetLibraries/Generic/src/MaxPool_fp32.c +++ b/TargetLibraries/Generic/src/MaxPool_fp32.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool_fp32.c - * Description: - * - * Date: 27.01.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/MaxPool_s8.c b/TargetLibraries/Generic/src/MaxPool_s8.c index 3e482f824a..ab46ab8d65 100644 --- a/TargetLibraries/Generic/src/MaxPool_s8.c +++ b/TargetLibraries/Generic/src/MaxPool_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool_s8.c - * Description: - * - * Date: 04.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/RQDiv_s8.c b/TargetLibraries/Generic/src/RQDiv_s8.c index 2ac7524969..30f83d5cbe 100644 --- a/TargetLibraries/Generic/src/RQDiv_s8.c +++ b/TargetLibraries/Generic/src/RQDiv_s8.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: RQDiv_s8.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/RQGELU_s8.c b/TargetLibraries/Generic/src/RQGELU_s8.c index 0e033a26a1..6113e5ddc5 100644 --- a/TargetLibraries/Generic/src/RQGELU_s8.c +++ b/TargetLibraries/Generic/src/RQGELU_s8.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: RQGELU_s8.c - * Description: - * - * $Date: 19.12.2022 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/RQHardswish.c b/TargetLibraries/Generic/src/RQHardswish.c index 6826c2c173..b780b166c9 100644 --- a/TargetLibraries/Generic/src/RQHardswish.c +++ b/TargetLibraries/Generic/src/RQHardswish.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: RQHardswish.c -# -# Last edited: 23.02.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Relu_fp32.c b/TargetLibraries/Generic/src/Relu_fp32.c index 775fb7c7f0..81b65f8516 100644 --- a/TargetLibraries/Generic/src/Relu_fp32.c +++ b/TargetLibraries/Generic/src/Relu_fp32.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: Softmax_fp8.c - * Description: - * - * $Date: 22.01.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/RequantShift_s8.c b/TargetLibraries/Generic/src/RequantShift_s8.c index c9c55df32c..56a84260e0 100644 --- a/TargetLibraries/Generic/src/RequantShift_s8.c +++ b/TargetLibraries/Generic/src/RequantShift_s8.c @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: RequantShift_s8.c - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Softmax_fp32.c b/TargetLibraries/Generic/src/Softmax_fp32.c index 64c4ba6f3e..94673a661d 100644 --- a/TargetLibraries/Generic/src/Softmax_fp32.c +++ b/TargetLibraries/Generic/src/Softmax_fp32.c @@ -1,29 +1,9 @@ -/* ===================================================================== - * Title: Softmax_fp32.c - * Description: - * - * $Date: 23.01.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ + #include "DeeployBasicMath.h" #include diff --git a/TargetLibraries/Generic/src/Softmax_s8.c b/TargetLibraries/Generic/src/Softmax_s8.c index ae5b40eb55..be073f01d0 100644 --- a/TargetLibraries/Generic/src/Softmax_s8.c +++ b/TargetLibraries/Generic/src/Softmax_s8.c @@ -1,29 +1,7 @@ -/* ===================================================================== - * Title: Softmax_s8.c - * Description: - * - * $Date: 27.03.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/Util.c b/TargetLibraries/Generic/src/Util.c index e576e0114c..e73b6ff1d8 100644 --- a/TargetLibraries/Generic/src/Util.c +++ b/TargetLibraries/Generic/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 06.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/Generic/src/iRMSNorm_s8.c b/TargetLibraries/Generic/src/iRMSNorm_s8.c index e84c4075a0..529935a929 100644 --- a/TargetLibraries/Generic/src/iRMSNorm_s8.c +++ b/TargetLibraries/Generic/src/iRMSNorm_s8.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: iRMSNorm_s8.c - * Description: - * - * $Date: 20.02.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployBasicMath.h" diff --git a/TargetLibraries/MemPool/CMakeLists.txt b/TargetLibraries/MemPool/CMakeLists.txt index 351b112029..be2f481109 100644 --- a/TargetLibraries/MemPool/CMakeLists.txt +++ b/TargetLibraries/MemPool/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/MemPool/inc/CycleCounter.h b/TargetLibraries/MemPool/inc/CycleCounter.h index 52e24d2ee2..a1516f471e 100644 --- a/TargetLibraries/MemPool/inc/CycleCounter.h +++ b/TargetLibraries/MemPool/inc/CycleCounter.h @@ -1,51 +1,28 @@ -/* ===================================================================== - * Title: CycleCounter.h - * Description: - * - * Date: 06.12.2022 - * - * ===================================================================== */ - -/* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __DEEPLOY_MATH_CYCLE_HEADER_ -#define __DEEPLOY_MATH_CYCLE_HEADER_ - -#include - -// Resets the internal cycle and instruction counter to zero -void ResetTimer(void); - -// Starts the internal cycle and instruction counter -void StartTimer(void); - -// Stops the internal cycle and instruction counter -void StopTimer(void); - -// Returns the current number of cycles according to the internal cycle counter -uint32_t getCycles(void); - -// Returns the current number of instructions according to the internal -// instructions counter -uint32_t getInstr(void); - -#endif //__DEEPLOY_MATH_CYCLE_HEADER_ +/* + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DEEPLOY_MATH_CYCLE_HEADER_ +#define __DEEPLOY_MATH_CYCLE_HEADER_ + +#include + +// Resets the internal cycle and instruction counter to zero +void ResetTimer(void); + +// Starts the internal cycle and instruction counter +void StartTimer(void); + +// Stops the internal cycle and instruction counter +void StopTimer(void); + +// Returns the current number of cycles according to the internal cycle counter +uint32_t getCycles(void); + +// Returns the current number of instructions according to the internal +// instructions counter +uint32_t getInstr(void); + +#endif //__DEEPLOY_MATH_CYCLE_HEADER_ diff --git a/TargetLibraries/MemPool/inc/DeeployMath.h b/TargetLibraries/MemPool/inc/DeeployMath.h index 2ff40809bd..7dc9c54a0d 100644 --- a/TargetLibraries/MemPool/inc/DeeployMath.h +++ b/TargetLibraries/MemPool/inc/DeeployMath.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: DeeployMath.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/MemPool/inc/ITA.h b/TargetLibraries/MemPool/inc/ITA.h index 2bdda47bce..042173bb98 100644 --- a/TargetLibraries/MemPool/inc/ITA.h +++ b/TargetLibraries/MemPool/inc/ITA.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: ITA.h - * Description: - * - * Date: 03.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_ITA_HEADER_ diff --git a/TargetLibraries/MemPool/inc/constants.h b/TargetLibraries/MemPool/inc/constants.h index 6a3d2cae5c..c282ecd863 100644 --- a/TargetLibraries/MemPool/inc/constants.h +++ b/TargetLibraries/MemPool/inc/constants.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: constants.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_CONSTANTS_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/Convolution.h b/TargetLibraries/MemPool/inc/kernel/Convolution.h index 63ac4837c9..83988e566e 100644 --- a/TargetLibraries/MemPool/inc/kernel/Convolution.h +++ b/TargetLibraries/MemPool/inc/kernel/Convolution.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Convolution.h - * Description: - * - * Date: 02.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_CONVOLUTION_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/DWConvolution.h b/TargetLibraries/MemPool/inc/kernel/DWConvolution.h index e05ae7a770..f88259c591 100644 --- a/TargetLibraries/MemPool/inc/kernel/DWConvolution.h +++ b/TargetLibraries/MemPool/inc/kernel/DWConvolution.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: DWConvolution.h - * Description: - * - * Date: 09.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_DWCONVOLUTION_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/Gemm.h b/TargetLibraries/MemPool/inc/kernel/Gemm.h index 157a3d221a..aef7e522e4 100644 --- a/TargetLibraries/MemPool/inc/kernel/Gemm.h +++ b/TargetLibraries/MemPool/inc/kernel/Gemm.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Gemm.h - * Description: - * - * Date: 16.05.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/MHSA.h b/TargetLibraries/MemPool/inc/kernel/MHSA.h index a97f4ae601..0b696600e8 100644 --- a/TargetLibraries/MemPool/inc/kernel/MHSA.h +++ b/TargetLibraries/MemPool/inc/kernel/MHSA.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MHSA.h - * Description: - * - * Date: 08.02.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MHSA_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/MatMul.h b/TargetLibraries/MemPool/inc/kernel/MatMul.h index ad61bafd4d..bd355856d3 100644 --- a/TargetLibraries/MemPool/inc/kernel/MatMul.h +++ b/TargetLibraries/MemPool/inc/kernel/MatMul.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/MaxPool.h b/TargetLibraries/MemPool/inc/kernel/MaxPool.h index d8b02b558b..614db2d770 100644 --- a/TargetLibraries/MemPool/inc/kernel/MaxPool.h +++ b/TargetLibraries/MemPool/inc/kernel/MaxPool.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool.h - * Description: - * - * Date: 13.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MAXPOOL_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/RQGemm.h b/TargetLibraries/MemPool/inc/kernel/RQGemm.h index a548122482..65de18fcfb 100644 --- a/TargetLibraries/MemPool/inc/kernel/RQGemm.h +++ b/TargetLibraries/MemPool/inc/kernel/RQGemm.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQGemm.h - * Description: - * - * Date: 16.05.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RQGEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/RQMatMul.h b/TargetLibraries/MemPool/inc/kernel/RQMatMul.h index 3e4fd96e12..a5261fcd74 100644 --- a/TargetLibraries/MemPool/inc/kernel/RQMatMul.h +++ b/TargetLibraries/MemPool/inc/kernel/RQMatMul.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQMatMul.h - * Description: - * - * Date: 24.04.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RQMATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/RequantShift.h b/TargetLibraries/MemPool/inc/kernel/RequantShift.h index b995e31392..b0ff3cef03 100644 --- a/TargetLibraries/MemPool/inc/kernel/RequantShift.h +++ b/TargetLibraries/MemPool/inc/kernel/RequantShift.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RequantShift.h - * Description: - * - * Date: 24.04.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_REQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/kernel/Softmax.h b/TargetLibraries/MemPool/inc/kernel/Softmax.h index 4a21a4e2de..920b59a1d3 100644 --- a/TargetLibraries/MemPool/inc/kernel/Softmax.h +++ b/TargetLibraries/MemPool/inc/kernel/Softmax.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Softmax.h - * Description: - * - * Date: 25.04.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/MemPool/inc/macros.h b/TargetLibraries/MemPool/inc/macros.h index 2d36e2334a..a6e0b231e0 100644 --- a/TargetLibraries/MemPool/inc/macros.h +++ b/TargetLibraries/MemPool/inc/macros.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: macros.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MACROS_HEADER_ diff --git a/TargetLibraries/MemPool/src/Convolution_s8.c b/TargetLibraries/MemPool/src/Convolution_s8.c index a81673e507..de1954145e 100644 --- a/TargetLibraries/MemPool/src/Convolution_s8.c +++ b/TargetLibraries/MemPool/src/Convolution_s8.c @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: Convolution_s8.c - * Description: - * - * Date: 02.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/CycleCounter.c b/TargetLibraries/MemPool/src/CycleCounter.c index 6e0be0eb97..b6ec31e09e 100644 --- a/TargetLibraries/MemPool/src/CycleCounter.c +++ b/TargetLibraries/MemPool/src/CycleCounter.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: CycleCounter.c - * Description: - * - * Date: 06.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/DWConvolution_s8.c b/TargetLibraries/MemPool/src/DWConvolution_s8.c index 00b5070fbd..18f8bffc0f 100644 --- a/TargetLibraries/MemPool/src/DWConvolution_s8.c +++ b/TargetLibraries/MemPool/src/DWConvolution_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: DWConvolution_s8.c - * Description: - * - * Date: 09.01.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/Gemm_s8.c b/TargetLibraries/MemPool/src/Gemm_s8.c index e5eba7e73b..73f56203a2 100644 --- a/TargetLibraries/MemPool/src/Gemm_s8.c +++ b/TargetLibraries/MemPool/src/Gemm_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Gemm_s8.c - * Description: - * - * Date: 16.05.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/ITA.c b/TargetLibraries/MemPool/src/ITA.c index ee1a4cbd57..3db7bdaccd 100644 --- a/TargetLibraries/MemPool/src/ITA.c +++ b/TargetLibraries/MemPool/src/ITA.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: ITA.c - * Description: - * - * Date: 5.12.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/MHSA_s8.c b/TargetLibraries/MemPool/src/MHSA_s8.c index 9b3570ec9b..9f071526ca 100644 --- a/TargetLibraries/MemPool/src/MHSA_s8.c +++ b/TargetLibraries/MemPool/src/MHSA_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: M4HSA_s8.c - * Description: - * - * Date: 08.02.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/MatMul_s16.c b/TargetLibraries/MemPool/src/MatMul_s16.c index b28bf002c0..df54e856db 100644 --- a/TargetLibraries/MemPool/src/MatMul_s16.c +++ b/TargetLibraries/MemPool/src/MatMul_s16.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s16.c - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/MatMul_s32.c b/TargetLibraries/MemPool/src/MatMul_s32.c index 6b04fc2536..6b78f2d2a9 100644 --- a/TargetLibraries/MemPool/src/MatMul_s32.c +++ b/TargetLibraries/MemPool/src/MatMul_s32.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s32.c - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/MatMul_s8.c b/TargetLibraries/MemPool/src/MatMul_s8.c index 81ddcf585c..ca0ac4fb5b 100644 --- a/TargetLibraries/MemPool/src/MatMul_s8.c +++ b/TargetLibraries/MemPool/src/MatMul_s8.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s8.c - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/MaxPool_s8.c b/TargetLibraries/MemPool/src/MaxPool_s8.c index 94e3f6175e..97587ec534 100644 --- a/TargetLibraries/MemPool/src/MaxPool_s8.c +++ b/TargetLibraries/MemPool/src/MaxPool_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool_s8.c - * Description: - * - * Date: 13.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/RQGemm_s8.c b/TargetLibraries/MemPool/src/RQGemm_s8.c index f983ef587e..4cc395687f 100644 --- a/TargetLibraries/MemPool/src/RQGemm_s8.c +++ b/TargetLibraries/MemPool/src/RQGemm_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQGemm_s8.c - * Description: - * - * Date: 16.05.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/RQMatMul_s8.c b/TargetLibraries/MemPool/src/RQMatMul_s8.c index 8a499c273b..28fea567df 100644 --- a/TargetLibraries/MemPool/src/RQMatMul_s8.c +++ b/TargetLibraries/MemPool/src/RQMatMul_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQMatMul_s8.c - * Description: - * - * Date: 24.04.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/RequantShift_s8.c b/TargetLibraries/MemPool/src/RequantShift_s8.c index c71942303e..51273aefac 100644 --- a/TargetLibraries/MemPool/src/RequantShift_s8.c +++ b/TargetLibraries/MemPool/src/RequantShift_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RequantShift_s8.c - * Description: - * - * Date: 24.04.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/Softmax_s8.c b/TargetLibraries/MemPool/src/Softmax_s8.c index cefe3eca22..cf53de43eb 100644 --- a/TargetLibraries/MemPool/src/Softmax_s8.c +++ b/TargetLibraries/MemPool/src/Softmax_s8.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: Softmax_s8.c - * Description: - * - * $Date: 25.04.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/MemPool/src/Util.c b/TargetLibraries/MemPool/src/Util.c index 315469c819..ae02076557 100644 --- a/TargetLibraries/MemPool/src/Util.c +++ b/TargetLibraries/MemPool/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployMath.h" diff --git a/TargetLibraries/PULPOpen/CMakeLists.txt b/TargetLibraries/PULPOpen/CMakeLists.txt index fde35caec3..0b9a3247e7 100644 --- a/TargetLibraries/PULPOpen/CMakeLists.txt +++ b/TargetLibraries/PULPOpen/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake index 0bafa56fbf..64452165ff 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-base.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(PULP_SDK_HOME $ENV{PULP_SDK_HOME}) diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake index f7c84d9bc4..3ab74d58bc 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-pulp-open.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 include(cmake/pulp-sdk-base.cmake) diff --git a/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake b/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake index e974cfd1e1..45fdd881a7 100644 --- a/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake +++ b/TargetLibraries/PULPOpen/cmake/pulp-sdk-siracusa.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 include(cmake/pulp-sdk-base.cmake) diff --git a/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h b/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h index 5e5b4142cb..f6e8308c97 100644 --- a/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h +++ b/TargetLibraries/PULPOpen/inc/DeeployPULPMath.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: DeeployMath.h - * Description: - * - * $Date: 30.12.2021 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/dory_mem.h b/TargetLibraries/PULPOpen/inc/dory_mem.h index 35a06cfd6c..ccd36a37d6 100644 --- a/TargetLibraries/PULPOpen/inc/dory_mem.h +++ b/TargetLibraries/PULPOpen/inc/dory_mem.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: dory_mem.h - * Description: - * - * $Date: 12.12.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __MEM_H__ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Conv.h b/TargetLibraries/PULPOpen/inc/kernel/Conv.h index b573df2d7b..f5382a339b 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Conv.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Conv.h @@ -1,29 +1,7 @@ - -/* ===================================================================== - * Title: Conv.h - * Description: - * - * $Date: 05.04.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_CONV_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/GELU.h b/TargetLibraries/PULPOpen/inc/kernel/GELU.h index c2a311fdec..8b2af4ec55 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/GELU.h +++ b/TargetLibraries/PULPOpen/inc/kernel/GELU.h @@ -1,29 +1,7 @@ - -/* ===================================================================== - * Title: GELU.h - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_GELU_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h b/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h index 78e09e9223..43e9c55cf4 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Layernorm.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: Layernorm.h - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_LAYERNORM_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Matmul.h b/TargetLibraries/PULPOpen/inc/kernel/Matmul.h index c48460b420..9176801b58 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Matmul.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Matmul.h @@ -1,30 +1,7 @@ - - -/* ===================================================================== - * Title: Matmul.h - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h b/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h index ca5a604286..b37487439f 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h +++ b/TargetLibraries/PULPOpen/inc/kernel/MaxPool.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: Maxpool.h - * Description: - * - * $Date: 05.04.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MAXPOOL_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h b/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h index 3c08cb7a91..407d97f903 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h +++ b/TargetLibraries/PULPOpen/inc/kernel/RQiHardswish.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: RQiHardswish.h - * Description: - * - * $Date: 15.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RQIHARDSWISH_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Relu.h b/TargetLibraries/PULPOpen/inc/kernel/Relu.h index 4b1246c750..1c49bd1cd8 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Relu.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Relu.h @@ -1,29 +1,7 @@ - -/* ===================================================================== - * Title: Relu.h - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RELU_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h b/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h index 70e12accca..3e5da558d2 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h +++ b/TargetLibraries/PULPOpen/inc/kernel/RequantShift.h @@ -1,31 +1,7 @@ -/* ===================================================================== - * Title: RequantShift_s8.c - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_REQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/Softmax.h b/TargetLibraries/PULPOpen/inc/kernel/Softmax.h index 9bc3570738..d696a5c27a 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/Softmax.h +++ b/TargetLibraries/PULPOpen/inc/kernel/Softmax.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: iSoftmax.h - * Description: - * - * $Date: 13.11.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h b/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h index 963f2dfb1c..7f795ee115 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h +++ b/TargetLibraries/PULPOpen/inc/kernel/UniformRequantShift.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: UniformRequantShift.h -# -# Last edited: 12.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ #define __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/gemm.h b/TargetLibraries/PULPOpen/inc/kernel/gemm.h index 950182dee1..863bb2102c 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/gemm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/gemm.h @@ -1,29 +1,7 @@ - -/* ===================================================================== - * Title: gemm.h - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/gemv.h b/TargetLibraries/PULPOpen/inc/kernel/gemv.h index a4a67bc4df..f40934544b 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/gemv.h +++ b/TargetLibraries/PULPOpen/inc/kernel/gemv.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: vec2mat.h - * Description: - * - * $Date: 15.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_GEMV_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h b/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h index 766f1daf44..5e2cd3a54c 100644 --- a/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h +++ b/TargetLibraries/PULPOpen/inc/kernel/iRMSnorm.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: iRMSnorm.h - * Description: - * - * $Date: 14.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_IRMSNORM_KERNEL_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/mchan_siracusa.h b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h index 3c5e8f7324..c0ecc02ebb 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_siracusa.h +++ b/TargetLibraries/PULPOpen/inc/mchan_siracusa.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: mchan_siracusa.h -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Luka Macan, luka.macan@unibo.it, University of Bologna -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ // Default mchan base address #ifndef MCHAN_BASE_ADDR diff --git a/TargetLibraries/PULPOpen/inc/mchan_v6.h b/TargetLibraries/PULPOpen/inc/mchan_v6.h index ffd4045519..bf7cfc1ddb 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_v6.h +++ b/TargetLibraries/PULPOpen/inc/mchan_v6.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: mchan_v6.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ /* - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - * Adopted from PULP-SDK (https://github.com/pulp-platform/pulp-sdk), released - under Apache 2.0 - + * SPDX-License-Identifier: Apache-2.0 */ #ifndef __MCHAN_V6_H__ diff --git a/TargetLibraries/PULPOpen/inc/mchan_v7.h b/TargetLibraries/PULPOpen/inc/mchan_v7.h index 8f14a0efdc..1078584b5a 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_v7.h +++ b/TargetLibraries/PULPOpen/inc/mchan_v7.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: mchan_v7.h - * Description: - * - * $Date: 26.07.2024 - * - * ===================================================================== */ /* - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - - * Adopted from PULP-SDK (https://github.com/pulp-platform/pulp-sdk), released - under Apache 2.0 - + * SPDX-License-Identifier: Apache-2.0 */ #ifndef __MCHAN_V7_H__ diff --git a/TargetLibraries/PULPOpen/inc/pulp_core.h b/TargetLibraries/PULPOpen/inc/pulp_core.h index 1970fd7f1d..c6877ed587 100644 --- a/TargetLibraries/PULPOpen/inc/pulp_core.h +++ b/TargetLibraries/PULPOpen/inc/pulp_core.h @@ -1,28 +1,9 @@ -/* ---------------------------------------------------------------------- -# -# File: pulp_core.h -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Run Wang, runwang@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef __DEEPLOY_MATH_PULPCORE_HEADER_ #define __DEEPLOY_MATH_PULPCORE_HEADER_ diff --git a/TargetLibraries/PULPOpen/inc/types.h b/TargetLibraries/PULPOpen/inc/types.h index 1031a86859..802ea2ea1a 100644 --- a/TargetLibraries/PULPOpen/inc/types.h +++ b/TargetLibraries/PULPOpen/inc/types.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: types.h - * Description: - * - * Date: 11.11.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2024 ETH Zurich and University of Bologna. - * - * Authors: - * - Francesco Conti, University of Bologna + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_TYPES_HEADER_ diff --git a/TargetLibraries/PULPOpen/src/Convolution_fp32.c b/TargetLibraries/PULPOpen/src/Convolution_fp32.c index c62d449d65..c33ac31e88 100644 --- a/TargetLibraries/PULPOpen/src/Convolution_fp32.c +++ b/TargetLibraries/PULPOpen/src/Convolution_fp32.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Conv.c - * Description: Float32 version of Conv2D with NCHW format (pre-padded input) - * - * Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/GELU.c b/TargetLibraries/PULPOpen/src/GELU.c index 80d0cd933c..281d4674d0 100644 --- a/TargetLibraries/PULPOpen/src/GELU.c +++ b/TargetLibraries/PULPOpen/src/GELU.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: GELU.c - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "pmsis.h" diff --git a/TargetLibraries/PULPOpen/src/Gemm.c b/TargetLibraries/PULPOpen/src/Gemm.c index d1a21f976f..826960d4f3 100644 --- a/TargetLibraries/PULPOpen/src/Gemm.c +++ b/TargetLibraries/PULPOpen/src/Gemm.c @@ -1,31 +1,7 @@ - -/* ===================================================================== - * Title: Gemm.c - * Description: - * - * Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/Layernorm.c b/TargetLibraries/PULPOpen/src/Layernorm.c index 8cd10c37af..f8387ab5e2 100644 --- a/TargetLibraries/PULPOpen/src/Layernorm.c +++ b/TargetLibraries/PULPOpen/src/Layernorm.c @@ -1,31 +1,7 @@ - -/* ===================================================================== - * Title: Layernorm.c - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "pmsis.h" diff --git a/TargetLibraries/PULPOpen/src/Matmul.c b/TargetLibraries/PULPOpen/src/Matmul.c index 252c0df377..639da75f45 100644 --- a/TargetLibraries/PULPOpen/src/Matmul.c +++ b/TargetLibraries/PULPOpen/src/Matmul.c @@ -1,31 +1,7 @@ - -/* ===================================================================== - * Title: Matmul.c - * Description: - * - * $Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "pmsis.h" diff --git a/TargetLibraries/PULPOpen/src/MaxPool.c b/TargetLibraries/PULPOpen/src/MaxPool.c index 8490bae031..3b630b97cc 100644 --- a/TargetLibraries/PULPOpen/src/MaxPool.c +++ b/TargetLibraries/PULPOpen/src/MaxPool.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: MaxPool.c - * Description: - * - * Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/RQiHardswish.c b/TargetLibraries/PULPOpen/src/RQiHardswish.c index c9a79e6f80..a60247290c 100644 --- a/TargetLibraries/PULPOpen/src/RQiHardswish.c +++ b/TargetLibraries/PULPOpen/src/RQiHardswish.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: RQiHardswish.c - * Description: - * - * $Date: 15.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/Relu.c b/TargetLibraries/PULPOpen/src/Relu.c index bb003066af..4e309bc092 100644 --- a/TargetLibraries/PULPOpen/src/Relu.c +++ b/TargetLibraries/PULPOpen/src/Relu.c @@ -1,31 +1,7 @@ - -/* ===================================================================== - * Title: Relu.c - * Description: - * - * Date: 05.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Run Wang, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/RequantShift.c b/TargetLibraries/PULPOpen/src/RequantShift.c index 9343be20f3..3f1f15f32b 100644 --- a/TargetLibraries/PULPOpen/src/RequantShift.c +++ b/TargetLibraries/PULPOpen/src/RequantShift.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: RequantShift_s8.c - * Description: - * - * Date: 19.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese, ETH Zurich - * - Victor Jung, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/Softmax.c b/TargetLibraries/PULPOpen/src/Softmax.c index 9b8244d65a..3fd60111fe 100644 --- a/TargetLibraries/PULPOpen/src/Softmax.c +++ b/TargetLibraries/PULPOpen/src/Softmax.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: iSoftmax.c - * Description: - * - * $Date: 13.11.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/UniformRequantShift.c b/TargetLibraries/PULPOpen/src/UniformRequantShift.c index 202bb14444..18a179154b 100644 --- a/TargetLibraries/PULPOpen/src/UniformRequantShift.c +++ b/TargetLibraries/PULPOpen/src/UniformRequantShift.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: UniformRequantShift.c -# -# Last edited: 12.03.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeployPULPMath.h" #include "pmsis.h" diff --git a/TargetLibraries/PULPOpen/src/Util.c b/TargetLibraries/PULPOpen/src/Util.c index 3aa62ff899..034beedf0f 100644 --- a/TargetLibraries/PULPOpen/src/Util.c +++ b/TargetLibraries/PULPOpen/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese, ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/PULPOpen/src/dory_mem.c b/TargetLibraries/PULPOpen/src/dory_mem.c index cfabec271b..95699a7492 100644 --- a/TargetLibraries/PULPOpen/src/dory_mem.c +++ b/TargetLibraries/PULPOpen/src/dory_mem.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: dory_mem.c - * Description: - * - * $Date: 12.12.2023 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "dory_mem.h" diff --git a/TargetLibraries/PULPOpen/src/gemv.c b/TargetLibraries/PULPOpen/src/gemv.c index c53e4d0b3f..a3c26cf3c1 100644 --- a/TargetLibraries/PULPOpen/src/gemv.c +++ b/TargetLibraries/PULPOpen/src/gemv.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: vec2mat.c - * Description: - * - * $Date: 15.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "pmsis.h" diff --git a/TargetLibraries/PULPOpen/src/iRMSnorm.c b/TargetLibraries/PULPOpen/src/iRMSnorm.c index 1361cf6e6f..de03d241d2 100644 --- a/TargetLibraries/PULPOpen/src/iRMSnorm.c +++ b/TargetLibraries/PULPOpen/src/iRMSnorm.c @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: iRMSnorm.c - * Description: - * - * $Date: 14.03.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: Moritz Scherer, ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeployPULPMath.h" diff --git a/TargetLibraries/Snitch/CMakeLists.txt b/TargetLibraries/Snitch/CMakeLists.txt index 859e8798c5..a2dd6703c7 100644 --- a/TargetLibraries/Snitch/CMakeLists.txt +++ b/TargetLibraries/Snitch/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/Snitch/inc/CycleCounter.h b/TargetLibraries/Snitch/inc/CycleCounter.h index f197055746..a1516f471e 100644 --- a/TargetLibraries/Snitch/inc/CycleCounter.h +++ b/TargetLibraries/Snitch/inc/CycleCounter.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: CycleCounter.h - * Description: - * - * Date: 06.12.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_CYCLE_HEADER_ diff --git a/TargetLibraries/Snitch/inc/DeeploySnitchMath.h b/TargetLibraries/Snitch/inc/DeeploySnitchMath.h index 193df1132e..e44d3c20c6 100644 --- a/TargetLibraries/Snitch/inc/DeeploySnitchMath.h +++ b/TargetLibraries/Snitch/inc/DeeploySnitchMath.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: DeeploySnitchMath.h - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/Snitch/inc/dmaStruct.h b/TargetLibraries/Snitch/inc/dmaStruct.h index e7cbdacbad..abbfc42b5a 100644 --- a/TargetLibraries/Snitch/inc/dmaStruct.h +++ b/TargetLibraries/Snitch/inc/dmaStruct.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: dmaStruct.h -# -# Last edited: 03.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_MATH_DMASTRUCT_HEADER_ #define __DEEPLOY_MATH_DMASTRUCT_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/Gemm.h b/TargetLibraries/Snitch/inc/kernel/Gemm.h index b1197b7863..d4a25a9d78 100644 --- a/TargetLibraries/Snitch/inc/kernel/Gemm.h +++ b/TargetLibraries/Snitch/inc/kernel/Gemm.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Gemm.h - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_GEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h b/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h index 8d01d35c15..2c3507113e 100644 --- a/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h +++ b/TargetLibraries/Snitch/inc/kernel/Gemm_fp32.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Gemm_fp32.h -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Taha El Bayed, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_MATH_GEMMFP32_KERNEL_HEADER_ #define __DEEPLOY_MATH_GEMMFP32_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/MatMul.h b/TargetLibraries/Snitch/inc/kernel/MatMul.h index be0cdeac7c..d4b9ba71ca 100644 --- a/TargetLibraries/Snitch/inc/kernel/MatMul.h +++ b/TargetLibraries/Snitch/inc/kernel/MatMul.h @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul.h - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/RQGemm.h b/TargetLibraries/Snitch/inc/kernel/RQGemm.h index b1d77c1e1c..dc72e1b3e8 100644 --- a/TargetLibraries/Snitch/inc/kernel/RQGemm.h +++ b/TargetLibraries/Snitch/inc/kernel/RQGemm.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQGemm.h - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RQGEMM_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/RQMatMul.h b/TargetLibraries/Snitch/inc/kernel/RQMatMul.h index fdac512497..c58e25d516 100644 --- a/TargetLibraries/Snitch/inc/kernel/RQMatMul.h +++ b/TargetLibraries/Snitch/inc/kernel/RQMatMul.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQMatMul.h - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_RQMATMUL_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/Softmax.h b/TargetLibraries/Snitch/inc/kernel/Softmax.h index 32bb658846..c2d7596e7a 100644 --- a/TargetLibraries/Snitch/inc/kernel/Softmax.h +++ b/TargetLibraries/Snitch/inc/kernel/Softmax.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Softmax.h -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Taha El Bayed, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ #define __DEEPLOY_MATH_SOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h b/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h index 0035301985..32358e5fb8 100644 --- a/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h +++ b/TargetLibraries/Snitch/inc/kernel/UniformRequantShift.h @@ -1,30 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * - * File: UniformRequantShift.h - * - * Last edited: 30.05.2024 - * - * Copyright (C) 2024, ETH Zurich and University of Bologna. - * - * Authors: - * - Victor Jung, (jungvi@iis.ee.ethz.ch), ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_UNIFORMREQUANTSHIFT_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/iNoNorm.h b/TargetLibraries/Snitch/inc/kernel/iNoNorm.h index 91b9e8b628..694df5be29 100644 --- a/TargetLibraries/Snitch/inc/kernel/iNoNorm.h +++ b/TargetLibraries/Snitch/inc/kernel/iNoNorm.h @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: iNoNorm.h -# -# Last edited: 06.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __DEEPLOY_MATH_INONORM_KERNEL_HEADER_ #define __DEEPLOY_MATH_INONORM_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/kernel/iSoftmax.h b/TargetLibraries/Snitch/inc/kernel/iSoftmax.h index 91ab95d502..fb68d04adf 100644 --- a/TargetLibraries/Snitch/inc/kernel/iSoftmax.h +++ b/TargetLibraries/Snitch/inc/kernel/iSoftmax.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: iSoftmax.h - * Description: - * - * $Date: 30.05.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_ISOFTMAX_KERNEL_HEADER_ diff --git a/TargetLibraries/Snitch/inc/macros.h b/TargetLibraries/Snitch/inc/macros.h index a54bc24d89..bc1191d25a 100644 --- a/TargetLibraries/Snitch/inc/macros.h +++ b/TargetLibraries/Snitch/inc/macros.h @@ -1,29 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * - * File: macros.h - * - * Last edited: 30.05.2024 - * - * Copyright (C) 2024, ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_MACROS_HEADER_ diff --git a/TargetLibraries/Snitch/src/Add.c b/TargetLibraries/Snitch/src/Add.c index 094739cf1b..40b216f138 100644 --- a/TargetLibraries/Snitch/src/Add.c +++ b/TargetLibraries/Snitch/src/Add.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Add.c -# -# Last edited: 11.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/CycleCounter.c b/TargetLibraries/Snitch/src/CycleCounter.c index 1a3ccd133b..47724816f1 100644 --- a/TargetLibraries/Snitch/src/CycleCounter.c +++ b/TargetLibraries/Snitch/src/CycleCounter.c @@ -1,29 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * - * File: CycleCounter.c - * - * Last edited: 23.04.2024 - * - * Copyright (C) 2024, ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/Gemm_fp32.c b/TargetLibraries/Snitch/src/Gemm_fp32.c index 13dce6f9a8..9a79538e12 100644 --- a/TargetLibraries/Snitch/src/Gemm_fp32.c +++ b/TargetLibraries/Snitch/src/Gemm_fp32.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Gemm_fp32.c -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Taha El Bayed, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeploySnitchMath.h" #include "Gemm.h" diff --git a/TargetLibraries/Snitch/src/Gemm_s8.c b/TargetLibraries/Snitch/src/Gemm_s8.c index 85c9312664..c216815505 100644 --- a/TargetLibraries/Snitch/src/Gemm_s8.c +++ b/TargetLibraries/Snitch/src/Gemm_s8.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Gemm_s8.c -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Taha El Bayed, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeploySnitchMath.h" #include "Gemm.h" diff --git a/TargetLibraries/Snitch/src/MatMul_s16.c b/TargetLibraries/Snitch/src/MatMul_s16.c index f4c56ba14e..6ec2ac8502 100644 --- a/TargetLibraries/Snitch/src/MatMul_s16.c +++ b/TargetLibraries/Snitch/src/MatMul_s16.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s16.c - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/MatMul_s32.c b/TargetLibraries/Snitch/src/MatMul_s32.c index 4ba81a7442..3c4a8d3837 100644 --- a/TargetLibraries/Snitch/src/MatMul_s32.c +++ b/TargetLibraries/Snitch/src/MatMul_s32.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s32.c - * Description: - * - * Date: 29.11.2022 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/MatMul_s8.c b/TargetLibraries/Snitch/src/MatMul_s8.c index e9ad77f349..d20cf2a756 100644 --- a/TargetLibraries/Snitch/src/MatMul_s8.c +++ b/TargetLibraries/Snitch/src/MatMul_s8.c @@ -1,32 +1,7 @@ -/* ===================================================================== - * Title: MatMul_s8.c - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Samuel Riedel, ETH Zurich - * - Sergio Mazzola, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/RQGemm_s8.c b/TargetLibraries/Snitch/src/RQGemm_s8.c index cfbc867bd7..d4e0d4c660 100644 --- a/TargetLibraries/Snitch/src/RQGemm_s8.c +++ b/TargetLibraries/Snitch/src/RQGemm_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQGemm_s8.c - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2023 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/RQMatMul_s8.c b/TargetLibraries/Snitch/src/RQMatMul_s8.c index 083141505e..1f20ecf8c0 100644 --- a/TargetLibraries/Snitch/src/RQMatMul_s8.c +++ b/TargetLibraries/Snitch/src/RQMatMul_s8.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: RQMatMul_s8.c - * Description: - * - * Date: 30.05.2024 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/Softmax_fp32.c b/TargetLibraries/Snitch/src/Softmax_fp32.c index b5530808c0..b8abb27845 100644 --- a/TargetLibraries/Snitch/src/Softmax_fp32.c +++ b/TargetLibraries/Snitch/src/Softmax_fp32.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: Softmax_fp32.c -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Taha El Bayed, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/UniformRequantShift.c b/TargetLibraries/Snitch/src/UniformRequantShift.c index a45a0b7e33..c326f0f769 100644 --- a/TargetLibraries/Snitch/src/UniformRequantShift.c +++ b/TargetLibraries/Snitch/src/UniformRequantShift.c @@ -1,30 +1,7 @@ /* - * ---------------------------------------------------------------------- + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * - * File: UniformRequantShift.c - * - * Last edited: 30.05.2024 - * - * Copyright (C) 2024, ETH Zurich and University of Bologna. - * - * Authors: - * - Victor Jung, (jungvi@iis.ee.ethz.ch), ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich - * - * ---------------------------------------------------------------------- * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/Util.c b/TargetLibraries/Snitch/src/Util.c index 7325e66047..35ef97ea59 100644 --- a/TargetLibraries/Snitch/src/Util.c +++ b/TargetLibraries/Snitch/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 15.03.2023 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except pSrcA compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to pSrcA writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/iNoNorm.c b/TargetLibraries/Snitch/src/iNoNorm.c index 30b3c68492..ee39c08f1d 100644 --- a/TargetLibraries/Snitch/src/iNoNorm.c +++ b/TargetLibraries/Snitch/src/iNoNorm.c @@ -1,28 +1,8 @@ -/* ---------------------------------------------------------------------- -# -# File: iNoNorm.c -# -# Last edited: 06.06.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: -# - Victor Jung, jungvi@iis.ee.ethz.ch, ETH Zurich -# -# ---------------------------------------------------------------------- -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ +/* + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/iSoftmax.c b/TargetLibraries/Snitch/src/iSoftmax.c index 41194a969f..9cd6c0f641 100644 --- a/TargetLibraries/Snitch/src/iSoftmax.c +++ b/TargetLibraries/Snitch/src/iSoftmax.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: iSoftmax.c - * Description: - * - * $Date: 30.05.2024 - * - * ===================================================================== */ /* - * Copyright (C) 2020 ETH Zurich and University of Bologna. - * - * Author: - * - Moritz Scherer, ETH Zurich - * - Philip Wiese (wiesep@iis.ee.ethz.ch), ETH Zurich + * SPDX-FileCopyrightText: 2020 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c b/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c index 3349581a52..b735e60704 100644 --- a/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c +++ b/TargetLibraries/Snitch/src/snitch_nn_add_i8_i8_i8.c @@ -1,23 +1,7 @@ /* - * pulp_nn_add_i8_i8_i8.c - * Georg Rutishauser - * Victor Jung - * - * Copyright (C) 2018-2020 University of Bologna + * SPDX-FileCopyrightText: 2018 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySnitchMath.h" diff --git a/TargetLibraries/SoftHier/CMakeLists.txt b/TargetLibraries/SoftHier/CMakeLists.txt index cbe0cb8032..1ae3a51f59 100644 --- a/TargetLibraries/SoftHier/CMakeLists.txt +++ b/TargetLibraries/SoftHier/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 file(GLOB_RECURSE SOURCES diff --git a/TargetLibraries/SoftHier/inc/DeeploySoftHierMath.h b/TargetLibraries/SoftHier/inc/DeeploySoftHierMath.h index 5a77b83a49..e54b3be47d 100644 --- a/TargetLibraries/SoftHier/inc/DeeploySoftHierMath.h +++ b/TargetLibraries/SoftHier/inc/DeeploySoftHierMath.h @@ -1,28 +1,7 @@ -/* ===================================================================== - * Title: DeeployMath.h - * Description: - * - * $Date: 07.06.2025 - * - * ===================================================================== */ /* - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Author: Bowen Wang , ETH Zurich + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_MATH_HEADER_ diff --git a/TargetLibraries/SoftHier/inc/types.h b/TargetLibraries/SoftHier/inc/types.h index 4d57747402..04720e14b4 100644 --- a/TargetLibraries/SoftHier/inc/types.h +++ b/TargetLibraries/SoftHier/inc/types.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: types.h - * Description: - * - * Date: 07.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Authors: - * - Bowen Wang , ETH Zurich + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_SOFTHIER_MATH_TYPES_HEADER_ diff --git a/TargetLibraries/SoftHier/inc/util.h b/TargetLibraries/SoftHier/inc/util.h index 1997e1ffc7..8474e9fd0b 100644 --- a/TargetLibraries/SoftHier/inc/util.h +++ b/TargetLibraries/SoftHier/inc/util.h @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: util.h - * Description: - * - * Date: 07.06.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2022 ETH Zurich and University of Bologna. - * - * Authors: - * - Bowen Wang , ETH Zurich + * SPDX-FileCopyrightText: 2022 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef __DEEPLOY_BASIC_MATH_UTIL_HEADER_ diff --git a/TargetLibraries/SoftHier/src/Util.c b/TargetLibraries/SoftHier/src/Util.c index 3e1120459a..156953801b 100644 --- a/TargetLibraries/SoftHier/src/Util.c +++ b/TargetLibraries/SoftHier/src/Util.c @@ -1,30 +1,7 @@ -/* ===================================================================== - * Title: Util.c - * Description: - * - * Date: 06.05.2025 - * - * ===================================================================== */ - /* - * Copyright (C) 2025 ETH Zurich and University of Bologna. - * - * Authors: - * - Bowen Wang , ETH Zurich + * SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna * * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "DeeploySoftHierMath.h" diff --git a/cmake/Util.cmake b/cmake/Util.cmake index 983c6d9574..1e54dc680b 100644 --- a/cmake/Util.cmake +++ b/cmake/Util.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 macro(add_deeploy_library name) diff --git a/cmake/chimera/chimera-sdk.cmake b/cmake/chimera/chimera-sdk.cmake index 468cd1fb90..b01b03b28d 100644 --- a/cmake/chimera/chimera-sdk.cmake +++ b/cmake/chimera/chimera-sdk.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 add_compile_definitions( diff --git a/cmake/chimera/toolchain_llvm.cmake b/cmake/chimera/toolchain_llvm.cmake index b82cc971d4..6e613c0cb9 100644 --- a/cmake/chimera/toolchain_llvm.cmake +++ b/cmake/chimera/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/cmsis/cmsis.cmake b/cmake/cmsis/cmsis.cmake index e6427e736c..adcb7c7a36 100644 --- a/cmake/cmsis/cmsis.cmake +++ b/cmake/cmsis/cmsis.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 add_compile_definitions( diff --git a/cmake/cmsis/qemu.cmake b/cmake/cmsis/qemu.cmake index d9a2bec5f9..1c2bf650e8 100644 --- a/cmake/cmsis/qemu.cmake +++ b/cmake/cmsis/qemu.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TARGET_CPU "cortex-m4" CACHE STRING "Target CPU") diff --git a/cmake/cmsis/toolchain_gcc.cmake b/cmake/cmsis/toolchain_gcc.cmake index 4c4aa39058..aabf5c591b 100644 --- a/cmake/cmsis/toolchain_gcc.cmake +++ b/cmake/cmsis/toolchain_gcc.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX arm-none-eabi) diff --git a/cmake/cmsis/toolchain_llvm.cmake b/cmake/cmsis/toolchain_llvm.cmake index 76454e4e9d..6c747b1d9d 100644 --- a/cmake/cmsis/toolchain_llvm.cmake +++ b/cmake/cmsis/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/common.cmake b/cmake/common.cmake index eff1505f09..18437219d5 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) diff --git a/cmake/generic/generic.cmake b/cmake/generic/generic.cmake index eb58af3b2e..a1d2ba807b 100644 --- a/cmake/generic/generic.cmake +++ b/cmake/generic/generic.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 add_compile_definitions( diff --git a/cmake/generic/toolchain_llvm.cmake b/cmake/generic/toolchain_llvm.cmake index 88888d2acd..2dafa53857 100644 --- a/cmake/generic/toolchain_llvm.cmake +++ b/cmake/generic/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/mempool/mempool.cmake b/cmake/mempool/mempool.cmake index 2a71dcec09..77053c1e06 100644 --- a/cmake/mempool/mempool.cmake +++ b/cmake/mempool/mempool.cmake @@ -1,11 +1,10 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 ############################# ## Address configuration ## ############################# - # Boot address (in dec) set(boot_addr 2684354560 CACHE STRING "Boot address (in dec)") # A0000000 diff --git a/cmake/mempool/mempool.yaml b/cmake/mempool/mempool.yaml index b9e776dc35..f940a961b5 100644 --- a/cmake/mempool/mempool.yaml +++ b/cmake/mempool/mempool.yaml @@ -1,5 +1,5 @@ -# Copyright 2021 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/cmake/mempool/mempool_ita.cmake b/cmake/mempool/mempool_ita.cmake index 5fc050ec21..e19be8366c 100644 --- a/cmake/mempool/mempool_ita.cmake +++ b/cmake/mempool/mempool_ita.cmake @@ -1,11 +1,10 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 ############################# ## Address configuration ## ############################# - # Boot address (in dec) set(boot_addr 2684354560 CACHE STRING "Boot address (in dec)") # A0000000 diff --git a/cmake/mempool/mempool_ita.yaml b/cmake/mempool/mempool_ita.yaml index 3c26e30095..aa1504c637 100644 --- a/cmake/mempool/mempool_ita.yaml +++ b/cmake/mempool/mempool_ita.yaml @@ -1,5 +1,5 @@ -# Copyright 2021 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/cmake/mempool/minpool.cmake b/cmake/mempool/minpool.cmake index 8d93246fc8..664c4a8f27 100644 --- a/cmake/mempool/minpool.cmake +++ b/cmake/mempool/minpool.cmake @@ -1,11 +1,10 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 ############################# ## Address configuration ## ############################# - # Boot address (in dec) set(boot_addr 2684354560 CACHE STRING "Boot address (in dec)") # A0000000 diff --git a/cmake/mempool/minpool.yaml b/cmake/mempool/minpool.yaml index c80e9964df..436e0c5eec 100644 --- a/cmake/mempool/minpool.yaml +++ b/cmake/mempool/minpool.yaml @@ -1,5 +1,5 @@ -# Copyright 2021 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2021 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 --- diff --git a/cmake/mempool/toolchain_gcc.cmake b/cmake/mempool/toolchain_gcc.cmake index a02ea55ce5..58c38049bf 100644 --- a/cmake/mempool/toolchain_gcc.cmake +++ b/cmake/mempool/toolchain_gcc.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin/riscv32-unknown-elf) diff --git a/cmake/mempool/toolchain_llvm.cmake b/cmake/mempool/toolchain_llvm.cmake index d84dbff293..3340daf460 100644 --- a/cmake/mempool/toolchain_llvm.cmake +++ b/cmake/mempool/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/pulp/pulp-open/pulp-open.cmake b/cmake/pulp/pulp-open/pulp-open.cmake index bc60586b15..a58a1bd8e8 100644 --- a/cmake/pulp/pulp-open/pulp-open.cmake +++ b/cmake/pulp/pulp-open/pulp-open.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(PULPNNVERSION XPULPV2) diff --git a/cmake/pulp/pulp.cmake b/cmake/pulp/pulp.cmake index 56fb3dbbf3..8518804315 100644 --- a/cmake/pulp/pulp.cmake +++ b/cmake/pulp/pulp.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 add_compile_definitions( diff --git a/cmake/pulp/siracusa/siracusa.cmake b/cmake/pulp/siracusa/siracusa.cmake index bc60586b15..a58a1bd8e8 100644 --- a/cmake/pulp/siracusa/siracusa.cmake +++ b/cmake/pulp/siracusa/siracusa.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(PULPNNVERSION XPULPV2) diff --git a/cmake/pulp/toolchain_gcc.cmake b/cmake/pulp/toolchain_gcc.cmake index 4df6f0639f..18014a98b9 100644 --- a/cmake/pulp/toolchain_gcc.cmake +++ b/cmake/pulp/toolchain_gcc.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin/riscv32-unknown-elf) diff --git a/cmake/pulp/toolchain_llvm.cmake b/cmake/pulp/toolchain_llvm.cmake index 4e995c3b55..cf3fb80d6c 100644 --- a/cmake/pulp/toolchain_llvm.cmake +++ b/cmake/pulp/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/simulation.cmake b/cmake/simulation.cmake index b6a99cd408..756da8d282 100644 --- a/cmake/simulation.cmake +++ b/cmake/simulation.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 ######################### diff --git a/cmake/snitch/snitch.cmake b/cmake/snitch/snitch.cmake index 47b1a046b8..a67f3ddc54 100644 --- a/cmake/snitch/snitch.cmake +++ b/cmake/snitch/snitch.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 if(NOT DEFINED ENV{SNITCH_HOME}) diff --git a/cmake/snitch/snitch_cluster/snitch_cluster.cmake b/cmake/snitch/snitch_cluster/snitch_cluster.cmake index 765d4deb2d..91d9392bb0 100644 --- a/cmake/snitch/snitch_cluster/snitch_cluster.cmake +++ b/cmake/snitch/snitch_cluster/snitch_cluster.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(SNITCH_CLUSTER_HOME ${SNITCH_HOME}/target/snitch_cluster) diff --git a/cmake/snitch/toolchain_llvm.cmake b/cmake/snitch/toolchain_llvm.cmake index 51c63c554b..09f64b9817 100644 --- a/cmake/snitch/toolchain_llvm.cmake +++ b/cmake/snitch/toolchain_llvm.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 set(TOOLCHAIN_PREFIX ${TOOLCHAIN_INSTALL_DIR}/bin) diff --git a/cmake/softhier/softhier_gvsoc.cmake b/cmake/softhier/softhier_gvsoc.cmake index ca21b63d97..198649f1ee 100644 --- a/cmake/softhier/softhier_gvsoc.cmake +++ b/cmake/softhier/softhier_gvsoc.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 macro(add_gvsoc_emulation name) diff --git a/cmake/softhier/toolchain_gcc.cmake b/cmake/softhier/toolchain_gcc.cmake index 1bea73b268..16ff0e5234 100644 --- a/cmake/softhier/toolchain_gcc.cmake +++ b/cmake/softhier/toolchain_gcc.cmake @@ -1,5 +1,5 @@ -# Copyright 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +# # SPDX-License-Identifier: Apache-2.0 add_compile_definitions( diff --git a/docs/Makefile b/docs/Makefile index 22e9a64c15..0009e947eb 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,8 +1,6 @@ -# Copyright 2024 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# Moritz Scherer +# SPDX-License-Identifier: Apache-2.0 SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build diff --git a/docs/_templates/custom-class-template.rst b/docs/_templates/custom-class-template.rst index aa311868fb..8f52d154cb 100644 --- a/docs/_templates/custom-class-template.rst +++ b/docs/_templates/custom-class-template.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + {{ fullname | escape | underline}} .. currentmodule:: {{ module }} diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst index 6adfe405db..edd7d130e0 100644 --- a/docs/_templates/custom-module-template.rst +++ b/docs/_templates/custom-module-template.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + {{ fullname | escape | underline}} .. automodule:: {{ fullname }} diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html index 137438b750..f4f59a671d 100644 --- a/docs/_templates/versions.html +++ b/docs/_templates/versions.html @@ -1,3 +1,9 @@ + +

Version: {{ current_version }} diff --git a/docs/apidocs.rst b/docs/apidocs.rst index a7da36f9e5..29b5495a13 100644 --- a/docs/apidocs.rst +++ b/docs/apidocs.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + API Reference ************* diff --git a/docs/conf.py b/docs/conf.py index e8f7ce201c..6ca3d33c6f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,27 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# File: conf.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os import subprocess diff --git a/docs/index.rst b/docs/index.rst index 23bd5db472..f765a041cd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + Deeploy Documentation ===================== diff --git a/docs/make.bat b/docs/make.bat index 32bb24529f..bb6fa61b30 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,3 +1,7 @@ +@REM SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +@REM +@REM SPDX-License-Identifier: Apache-2.0 + @ECHO OFF pushd %~dp0 diff --git a/docs/tutorials/debugging.rst b/docs/tutorials/debugging.rst index 0e0dd5a885..5145ae79c8 100644 --- a/docs/tutorials/debugging.rst +++ b/docs/tutorials/debugging.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + Debugging ========= diff --git a/docs/tutorials/overview.rst b/docs/tutorials/overview.rst index a76bb1e1e3..0b3d97c761 100644 --- a/docs/tutorials/overview.rst +++ b/docs/tutorials/overview.rst @@ -1,3 +1,7 @@ +.. SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +.. +.. SPDX-License-Identifier: Apache-2.0 + Tutorials ********* diff --git a/pyproject.toml b/pyproject.toml index 758bbae9ba..4bd7cb3e70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + [project] name = "PULP-Deeploy" version = '0.2.1' diff --git a/requirements-dev.txt b/requirements-dev.txt index a90062f113..6d047b4957 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + # Quality of life netron debugpy @@ -17,6 +21,7 @@ isort==5.12.0 autoflake==2.3.0 yamllint==1.37.1 clang-format +reuse # Documentation sphinx diff --git a/scripts/gen_changelog.py b/scripts/gen_changelog.py index d54cd42355..474eff405e 100644 --- a/scripts/gen_changelog.py +++ b/scripts/gen_changelog.py @@ -1,28 +1,6 @@ -# ---------------------------------------------------------------------- +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna # -# File: MchanDma.py -# -# Last edited: 11.09.2025 -# -# Copyright (C) 2025, ETH Zurich and University of Bologna. -# -# Author: -# - Philip Wiese, ETH Zurich -# -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import re import subprocess diff --git a/scripts/reuse_skip_wrapper.py b/scripts/reuse_skip_wrapper.py new file mode 100755 index 0000000000..74d3c79696 --- /dev/null +++ b/scripts/reuse_skip_wrapper.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +import shutil +import subprocess + + +def skip(file: str) -> bool: + # Skip license directory + if "LICENSES" in os.path.split(file): + return True + + return False + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(prog = "license-fix.py", + usage = "%(prog)s [OPTIONS] FILE ...", + description = "Helper script to fix the licenses with pre-commit") + parser.add_argument("files", nargs = "+") + + args = parser.parse_args() + + files = [f for f in args.files if not skip(f)] + + reuse_path = shutil.which("reuse") + if not reuse_path: + reuse_path = "python -m reuse" + try: + subprocess.run(f"{reuse_path} lint-file {' '.join(files)}", shell = True, check = True) + except subprocess.CalledProcessError: + exit(1) diff --git a/setup.py b/setup.py index bd6d90c570..b89383d40a 100644 --- a/setup.py +++ b/setup.py @@ -1,27 +1,8 @@ -# ---------------------------------------------------------------------- -# -# File: setup.py -# -# Last edited: 26.07.2024 -# -# Copyright (C) 2024, ETH Zurich and University of Bologna. -# -# Author: Moritz Scherer, ETH Zurich +#!/usr/bin/env python + +# SPDX-FileCopyrightText: 2024 ETH Zurich and University of Bologna # -# ---------------------------------------------------------------------- # SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import setuptools From 362033f478ceb772399a6fd2367a8c93990a52cc Mon Sep 17 00:00:00 2001 From: Philip Wiese Date: Mon, 6 Oct 2025 18:49:39 +0200 Subject: [PATCH 10/28] Refactor Logging for Improved Debugging (#115) This pull request introduces several improvements and refactors across the codebase, focusing on enhanced logging, memory tracking, type checking, and developer usability. The most significant changes include replacing print statements with structured logging, adding detailed memory usage tracking for buffers, improving type and level checking for data types, and providing more informative string representations and debugging messages for core classes. All runners and the generation scripts support different verbosity levels: - `-v`: Show errors, warning and info messages - `-vv`: Show errors, warnings, info and debug messages - `-vvv`: Maximum verbosity with information about where the message was emitted. Also enable verbose compilation during the build step for the test runners. ## Added - Logging and Error Handling Improvements: Replaced all `print` statements with structured logging using `DEFAULT_LOGGER` throughout the codebase, improving consistency and enabling better log management. - Added debug-level logs to type checking and parsing routines to indicate success/failure and binding exhaustion, aiding troubleshooting. - Implemented `__repr__` methods for core classes (`NodeTemplate`, `NodeBinding`, `NodeMapper`) to provide more informative string representations for debugging and logging - Added `checkNumLevels` methods to relevant data type classes to validate that the number of levels assigned to buffers is supported by their type, and integrated warning logs if mismatches are detected during type inference. - Introduced a `sizeInBytes` method to `VariableBuffer`, `TransientBuffer`, and related classes to standardize buffer size calculation. - Report the maximum static and dynamic memory usage for all memory level: - Added dynamic and maximum memory usage tracking to `NetworkContext` via `_dynamicSize` and `_maxDynamicSize` dictionaries, and updated memory allocation/deallocation logic in `MemoryAllocation.py` to maintain these statistics per memory level. (This is only used for untitled platforms to track the maximum buffer size.) - Exposed new summary methods (`_printMemorySummary`, `_printInputOutputSummary`) in deployer wrappers and implemented input/output summary logging in `SignPropDeployer`. ## Changed - Deployer workflow now uses `prepare(...)` instead of `generateFunction(...)`. --- CHANGELOG.md | 7 + Deeploy/AbstractDataTypes.py | 16 +- .../MemoryAllocation.py | 38 +++ .../NetworkDeployerWrapper.py | 6 + .../NetworkDeployers/SignPropDeployer.py | 14 + .../OptimizationPasses/PassClasses.py | 3 +- .../TypeCheckers/SignPropTypeChecker.py | 13 +- Deeploy/DeeployTypes.py | 287 ++++++++++++++---- .../Bindings/AutoFutureBinding.py | 9 +- Deeploy/Logging.py | 62 ++++ .../NetworkDeployers/MemoryLevelDeployer.py | 48 ++- Deeploy/Targets/Chimera/Platform.py | 8 +- Deeploy/Targets/CortexM/Platform.py | 26 +- Deeploy/Targets/Generic/Platform.py | 24 +- Deeploy/Targets/MemPool/Platform.py | 34 ++- Deeploy/Targets/Neureka/Platform.py | 2 +- Deeploy/Targets/PULPOpen/Platform.py | 3 +- Deeploy/Targets/Snitch/Platform.py | 3 +- Deeploy/Targets/SoftHier/Platform.py | 2 +- Deeploy/TilingExtension/MemoryScheduler.py | 2 +- Deeploy/TilingExtension/TilerExtension.py | 46 ++- Deeploy/TilingExtension/TilerModel.py | 14 +- DeeployTest/generateNetwork.py | 44 +-- DeeployTest/testMVP.py | 52 ++-- DeeployTest/testUtils/codeGenerate.py | 2 + DeeployTest/testUtils/testRunner.py | 54 ++-- pyproject.toml | 1 + 27 files changed, 588 insertions(+), 232 deletions(-) create mode 100644 Deeploy/Logging.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d14570d4b1..b3d601536a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Refactor Logging for Improved Debugging [#115](https://github.com/pulp-platform/Deeploy/pull/115) - Add reuse-tool as an SPDX license header linter [#113](https://github.com/pulp-platform/Deeploy/pull/113) - Bug fixes, API Cleanup and Reduce Compiler Warning on PULP [#112](https://github.com/pulp-platform/Deeploy/pull/112) - Fix PULP GEMM `batch` serialization [#109](https://github.com/pulp-platform/Deeploy/pull/109) @@ -39,6 +40,11 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Reshape operator support for PULP (`ReshapeTemplate` in bindings) - Missing class attributes in `Closure.py` - reuse_skip_wrapper.py to manually skip files +- Centralized logging with `DEFAULT_LOGGER`, replacing `print` statements +- Debug logs for type checking/parsing; `__repr__` for core classes +- Buffer utilities: `checkNumLevels` validation and `sizeInBytes` method +- Per–memory-level usage tracking and worst-case reporting in `NetworkContext` +- Memory/I/O summaries and input/output logging in deployers ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -65,6 +71,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Removed unnecessary includes from the PULP platform header list, such as `DeeployBasicMath.h`, for cleaner code generation - Changed types and added correct casts to fix many compiler warnings in the PULP target library - Use [reuse-tool](https://github.com/fsfe/reuse-tool) in pre-commit, CI, and Makefile for SPDX license header linting +- Deployer workflow now uses `prepare(...)` instead of `generateFunction(...)`. ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon diff --git a/Deeploy/AbstractDataTypes.py b/Deeploy/AbstractDataTypes.py index b3b0128621..feeebe939b 100644 --- a/Deeploy/AbstractDataTypes.py +++ b/Deeploy/AbstractDataTypes.py @@ -21,6 +21,8 @@ _DeeployType = TypeVar("_DeeployType", _PointerType, _ImmediateType, _StructType) _PythonType = TypeVar("_PythonType", str, int, float, Dict[str, "_PythonType"], Iterable["_PythonType"]) +from Deeploy.Logging import DEFAULT_LOGGER as log + class _ClassPropertyDescriptor(object): @@ -188,6 +190,10 @@ def typeMin(cls) -> int: else: return 0 + @_classproperty + def nLevels(cls) -> int: + return cls.typeMax - cls.typeMin + 1 + @classmethod def partialOrderUpcast(cls, otherCls: Type[Immediate]) -> bool: if issubclass(otherCls, IntegerImmediate): @@ -213,6 +219,10 @@ def checkValue(cls, value: Union[int, Iterable[int], np.ndarray], ctxt: Optional return False return True + @classmethod + def fitsNumLevels(cls, nLevels: int) -> bool: + return nLevels <= cls.nLevels + class FloatImmediate(Immediate[Union[float, Iterable[float]], _ImmediateType]): typeMantissa: int #: int: Represents the number of bits reserved for the mantissa part @@ -308,7 +318,7 @@ def checkValue(cls, value: Optional[str], ctxt: Optional[_NetworkContext] = None return False if value is None or value == "NULL": - print("WARNING: Setting pointer value to NULL - Referenced data is invalid!") + log.warning("Setting pointer value to NULL - Referenced data is invalid!") return True reference = ctxt.lookup(value) @@ -332,6 +342,10 @@ def checkPromotion(cls, _value: Union[Optional[str], Pointer], ctxt: Optional[_N value = _value return cls.checkValue(value, ctxt) + @classmethod + def fitsNumLevels(cls, nLevels: int) -> bool: + return cls.referencedType.fitsNumLevels(nLevels) + def __init__(self, _value: Union[Optional[str], Pointer], ctxt: Optional[_NetworkContext] = None): """Initializes a pointer to a registered object in the NetworkContext diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py index ff0aceea2e..b73fcafe31 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py @@ -122,13 +122,31 @@ def apply(self, for buffer in reversed(self.topologicallySortBuffers(outputs + transients)): assert buffer._live == False, f"Tried to allocate already live buffer {buffer.name}" buffer._live = True + + memoryLevel = "None" if not hasattr(buffer, "_memoryLevel") else buffer._memoryLevel + if memoryLevel not in ctxt._dynamicSize: + ctxt._dynamicSize[memoryLevel] = int(buffer.sizeInBytes()) + else: + ctxt._dynamicSize[memoryLevel] += int(buffer.sizeInBytes()) + executionBlock.addLeft(buffer.allocTemplate, buffer._bufferRepresentation()) + for levels in ctxt._dynamicSize.keys(): + if levels not in ctxt._maxDynamicSize: + ctxt._maxDynamicSize[levels] = max(0, ctxt._dynamicSize[levels]) + else: + ctxt._maxDynamicSize[levels] = max(ctxt._maxDynamicSize.get(levels, 0), ctxt._dynamicSize[levels]) + for buffer in inputs + transients: assert buffer._live == True, f"Tried to deallocate already dead buffer {buffer.name}" buffer._live = False # Don't deallocate if it's an alias of a live buffer if not buffer.has_live_ancestors(ctxt = ctxt): + memoryLevel = "None" if not hasattr(buffer, "_memoryLevel") else buffer._memoryLevel + if memoryLevel not in ctxt._dynamicSize: + ctxt._dynamicSize[memoryLevel] = 0 + else: + ctxt._dynamicSize[memoryLevel] -= int(buffer.sizeInBytes()) executionBlock.addRight(buffer.deallocTemplate, buffer._bufferRepresentation()) return ctxt, executionBlock @@ -157,10 +175,30 @@ def apply(self, for buffer in outputs + transients: assert buffer._live == False, f"Tried to allocate already live buffer {buffer.name}" + + memoryLevel = "None" if not hasattr(buffer, "_memoryLevel") else buffer._memoryLevel + if memoryLevel not in ctxt._dynamicSize: + ctxt._dynamicSize[memoryLevel] = int(buffer.sizeInBytes()) + else: + ctxt._dynamicSize[memoryLevel] += int(buffer.sizeInBytes()) + buffer._live = True + for levels in ctxt._dynamicSize.keys(): + if levels not in ctxt._maxDynamicSize: + ctxt._maxDynamicSize[levels] = max(0, ctxt._dynamicSize[levels]) + else: + ctxt._maxDynamicSize[levels] = max(ctxt._maxDynamicSize.get(levels, 0), ctxt._dynamicSize[levels]) + for buffer in inputs + transients: assert buffer._live == True, f"Tried to deallocate already dead buffer {buffer.name}" + + memoryLevel = "None" if not hasattr(buffer, "_memoryLevel") else buffer._memoryLevel + if memoryLevel not in ctxt._dynamicSize: + ctxt._dynamicSize[memoryLevel] = 0 + else: + ctxt._dynamicSize[memoryLevel] -= int(buffer.sizeInBytes()) + buffer._live = False return ctxt, executionBlock diff --git a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py index 4b9568bdde..90ce3f99ad 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py @@ -75,3 +75,9 @@ def generateBufferAllocationCode(self) -> str: # MultiEngineDeployer augment def _mapNode(self, node: gs.Node) -> Union[ONNXLayer, Any]: return self._innerObject._mapNode(node) + + def _printMemorySummary(self): + return self._innerObject._printMemorySummary() + + def _printInputOutputSummary(self): + return self._innerObject._printInputOutputSummary() diff --git a/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py b/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py index fc9adf96be..7a9fbea1ae 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/SignPropDeployer.py @@ -8,6 +8,7 @@ from Deeploy.AbstractDataTypes import Pointer from Deeploy.DeeployTypes import DeploymentPlatform, NetworkDeployer, TopologyOptimizer +from Deeploy.Logging import DEFAULT_LOGGER as log class SignPropDeployer(NetworkDeployer): @@ -41,3 +42,16 @@ def _createIOBindings(self, ctxt, graph): nb.nLevels = (2**data_type.referencedType.typeWidth) return ctxt + + def _printInputOutputSummary(self): + log.info('Input:') + for buf in self.inputs(): + log.info( + f" - '{buf.name}': Type: {buf._type.referencedType.typeName}, nLevels: {buf.nLevels}, Signed: {buf._signed}, Offset: {self.inputOffsets[buf.name]}" + ) + + log.info('Output:') + for buf in self.outputs(): + log.info( + f" - '{buf.name}': Type: {buf._type.referencedType.typeName}, nLevels: {buf.nLevels}, Signed: {buf._signed}" + ) diff --git a/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py b/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py index dfca7743f2..f9c784b2e4 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/PassClasses.py @@ -7,6 +7,7 @@ import onnx_graphsurgeon as gs from Deeploy.DeeployTypes import NetworkContext +from Deeploy.Logging import DEFAULT_LOGGER as log from .Matchers import Match, NonBranchingMatcher, SubgraphMatcher @@ -129,7 +130,7 @@ def remove_subpass(self, name): try: del self._subpasses[name] except KeyError: - print(f"No subpass with name {name}, cannot remove!") + log.error(f"No subpass with name {name}, cannot remove!") except AttributeError: raise AttributeError("Cannot remove sub-pass before calling Pass.__init__!") diff --git a/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py b/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py index bb34147d23..c70628729b 100644 --- a/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py +++ b/Deeploy/CommonExtensions/TypeCheckers/SignPropTypeChecker.py @@ -6,7 +6,9 @@ import onnx_graphsurgeon as gs +from Deeploy.AbstractDataTypes import IntegerImmediate from Deeploy.DeeployTypes import ConstantBuffer, NetworkContext, NodeTypeChecker, OperatorRepresentation, VariableBuffer +from Deeploy.Logging import DEFAULT_LOGGER as log class SignPropTypeChecker(NodeTypeChecker): @@ -46,8 +48,15 @@ def typeInferOutput(self, ctxt: NetworkContext, node: gs.Node, nLevels = self._inferNumLevels(inputs, operatorRepresentation) signedness = self._inferSignedness(inputs, operatorRepresentation) - for obj, nLevels, sign in zip(outputs, nLevels, signedness): - obj.nLevels = nLevels + if nLevels is None or signedness is None: + return ctxt + for obj, nLevel, sign in zip(outputs, nLevels, signedness): + obj.nLevels = nLevel obj._signed = sign + if issubclass(obj._type.referencedType, IntegerImmediate) and not obj._type.fitsNumLevels(nLevel): + log.warning( + f"{obj.name} has {nLevel} levels, but {obj._type.referencedType.typeName} only supports {obj._type.referencedType.nLevels} levels." + ) + return ctxt diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index b638cbd594..e6ca25c9bd 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -5,9 +5,11 @@ from __future__ import annotations import copy +import math import os import pickle import re +import time from abc import abstractmethod from collections import OrderedDict, deque from dataclasses import dataclass @@ -22,6 +24,9 @@ from onnx.external_data_helper import convert_model_to_external_data from ortools.constraint_solver.pywrapcp import IntVar +from Deeploy.Logging import DEFAULT_LOGGER as log +from Deeploy.Logging import FAILURE_MARK, SUCCESS_MARK + from .AbstractDataTypes import BaseType, FloatImmediate, IntegerImmediate, Pointer, PointerClass, Struct, VoidType Shape = TypeVar("Shape", bound = Any) @@ -218,8 +223,8 @@ def generate(self, operatorRepresentation = {}, **kwargs) -> str: operatorRepresentation[f'RENDER_{key}'] = template.generate(**subNodeRep, **kwargs) callStack += self.template.render(**operatorRepresentation, **kwargs) except: - print(operatorRepresentation) - print(mako.exceptions.text_error_template().render()) + log.error(operatorRepresentation) + log.error(mako.exceptions.text_error_template().render()) raise KeyError(f"Template {self} failed!") return callStack @@ -374,6 +379,17 @@ def has_live_ancestors(self, ctxt: NetworkContext) -> bool: return False + def sizeInBytes(self) -> int: + """Returns the size of this VariableBuffer in bytes + + Returns + ------- + int + Size of this VariableBuffer in bytes + + """ + return (math.prod(self.shape) * (self._type.referencedType.typeWidth)) // 8 + class TransientBuffer(VariableBuffer): """Class to represent memory space required by kernels that is not covered by input and output tensors, e.g. im2col buffers in convolutions @@ -420,6 +436,9 @@ def __repr__(self) -> str: def fromVariableBuffer(cls, buffer: VariableBuffer): ret = cls(name = buffer.name, size = np.prod(buffer.shape) * buffer._type.typeWidth // 8) + def sizeInBytes(self) -> int: + return int(self.size) + class ConstantBuffer(VariableBuffer): """Class to represent compile-time constant tensors (weights, biases, other parameters) within Deeploy. @@ -562,6 +581,9 @@ def __init__(self, self.TransientBuffer = transientBuffer self.name = name + self._maxDynamicSize = {} #: int: Maximum dynamic memory size occupied by live buffers at any point in time + self._dynamicSize = {} #: int: Current dynamic memory size occupied by live buffers + def dealiasBuffer(self, name: str) -> str: """Function to find the underlying aliased VariableBuffer @@ -1408,6 +1430,11 @@ def typeCheck(self, ctxt: NetworkContext, node: gs.Node, self.annotateDict(newCtxt, node, operatorRepresentation) return (newCtxt, True) + def signature(self) -> str: + input_types_str = ", ".join([_type.referencedType.typeName for _type in self.input_types]) + output_types_str = ", ".join([_type.referencedType.typeName for _type in self.output_types]) + return f"({input_types_str}) -> {output_types_str}" + class ExecutionBlock(): """Deeploy abstraction to represent a operator whose kernel has been determined. Mostly used to apply various code transformations, and, finally, generate C Code @@ -1552,6 +1579,9 @@ def __init__(self, typeChecker: NodeTypeChecker, template: NodeTemplate, codeTra self.buffers: List[VariableBuffer] = [] self.codeTransformer: CodeTransformation = codeTransformer + def __repr__(self): + return f"{self.template.__class__.__name__}{self._typeChecker.signature()}" + @property def typeChecker(self): """Read-only wrapper around the encapsulated type checker @@ -1613,9 +1643,13 @@ def typeCheck(self, ctxt: NetworkContext, node: gs.Node, matches the node """ + newCtxt, ret = self.typeChecker.typeCheck(ctxt.copy(), node, operatorRepresentation) if ret: + log.debug(f" {SUCCESS_MARK} Type check passed for {self}") return newCtxt, True + else: + log.debug(f" {FAILURE_MARK} Type check failed for {self}") return ctxt, False @@ -1692,6 +1726,10 @@ def __init__(self, parser: NodeParser, bindings: List[NodeBinding]): self.discardedBindings = set() #: Set[NodeBinding]: Set of all bindings which have been tried unsuccessfully. + def __repr__(self): + bindings_str = "\n ".join([repr(binding) for binding in self.bindings]) + return f"{self.parser.__class__.__name__} [\n {bindings_str}\n]" + # Don't override this. Parses the networks with the correct data type def _parse(self, ctxt: NetworkContext, @@ -1701,7 +1739,10 @@ def _parse(self, newCtxt, ret = self.parser.parse(ctxt.copy(), node, default_channels_first, ioParse) if ret: + log.debug(f" {SUCCESS_MARK} Parser {self.parser.__class__.__name__} succeeded") return newCtxt, True + else: + log.debug(f" {FAILURE_MARK} Parser {self.parser.__class__.__name__} failed") return ctxt, False @@ -1711,6 +1752,10 @@ def _parseCtxt(self, default_channels_first: bool = True) -> Tuple[NetworkContext, bool]: newCtxt, ret = self.parser.parseNodeCtxt(ctxt.copy(), node, default_channels_first) + if ret: + log.debug(f" {SUCCESS_MARK} Context parsing succeeded with {self.parser.__class__.__name__}") + else: + log.debug(f" {FAILURE_MARK} Context parsing failed with {self.parser.__class__.__name__}") return (newCtxt, ret) def bindingsExhausted(self) -> bool: @@ -1755,7 +1800,8 @@ def typeCheck(self, ctxt: NetworkContext, node: gs.Graph) -> Tuple[NetworkContex failure """ - for binder in self.bindings: + + for idx, binder in enumerate(self.bindings): if binder in self.discardedBindings: continue @@ -1769,6 +1815,7 @@ def typeCheck(self, ctxt: NetworkContext, node: gs.Graph) -> Tuple[NetworkContex self.binder = binder return newCtxt, True + log.debug(f" ‼ All {len(self.bindings)} bindings exhausted for {self.parser.__class__.__name__}") return ctxt, False # Don't override this. This should annotate the output node with the correct data type @@ -1837,6 +1884,10 @@ def __init__(self, maps: List[NodeMapper]): ) #: Set[NodeMapper]: Set of all NodeMappers which cannot be used to represent this layer self.node: gs.Node = None #: gs.Node: The represented operator + def __repr__(self): + maps_str = "\n ".join([repr(mapper) for mapper in self.maps]) + return f"{self.__class__.__name__}(maps=[\n {maps_str}\n])" + def computeOps(self): """Returns the number of operations (1 MAC = 2 Ops) of this operator """ @@ -1978,12 +2029,14 @@ def parse(self, ctxt: NetworkContext, default_channels_first: bool) -> Tuple[Net """ + ioParse = True # iterate through all possible mappings and return the first that works for idx, mapper in enumerate(self.maps): if mapper in self.discardedMappers: + log.debug(f" â­ï¸ Skipping mapper {idx}: {mapper.parser.__class__.__name__} (previously discarded)") continue newCtxt = ctxt.copy() @@ -1998,11 +2051,13 @@ def parse(self, ctxt: NetworkContext, default_channels_first: bool) -> Tuple[Net self.mapper = mapper + # Perform broadcasting self.broadcast(newCtxt, default_channels_first) newCtxt, ret = mapper._parseCtxt(newCtxt, self.node, default_channels_first) if not ret: + log.debug(f" {FAILURE_MARK} Context parsing failed for {mapper.parser.__class__.__name__}") self.discardedMappers.add(mapper) continue @@ -2011,6 +2066,7 @@ def parse(self, ctxt: NetworkContext, default_channels_first: bool) -> Tuple[Net return newCtxt, True + log.debug(f" All {len(self.maps)} mappers exhausted for '{self.node.name}'") return ctxt, False def _broadcastToNpType(self, ty: Type[BaseType]): @@ -2049,6 +2105,9 @@ def typeCheck(self, ctxt: NetworkContext) -> Tuple[NetworkContext, bool]: failure """ + if not hasattr(self, 'mapper') or self.mapper is None: + log.debug(f" {FAILURE_MARK} ONNXLayer.typeCheck() - No mapper selected for '{self.node.name}'") + return ctxt, False newCtxt = ctxt.copy() newCtxt, ret = self.mapper.typeCheck(newCtxt, self.node) @@ -2174,7 +2233,8 @@ class TopologyOptimizer(): """ - def __init__(self, passes: List[TopologyOptimizationPass]): + def __init__(self, passes: List[TopologyOptimizationPass], name: str = "TopologyOptimizer"): + self.name = name self.passes = passes def optimize(self, graph: gs.Graph) -> Tuple[gs.Graph]: @@ -2192,8 +2252,11 @@ def optimize(self, graph: gs.Graph) -> Tuple[gs.Graph]: """ for _pass in self.passes: + start_time = time.perf_counter() graph = _pass.apply(graph) graph.cleanup().toposort() + end_time = time.perf_counter() + log.debug(f" - Applied {_pass.__class__.__name__} ({(end_time - start_time)*1E3:.3f} ms)") return graph @@ -2363,6 +2426,9 @@ def canExecute(self, node: gs.Node) -> bool: """ return node.op in self.Mapping + def __repr__(self): + return f"{self.__class__.__name__}(name='{self.name}', mappings={list(self.Mapping.keys())})" + class DeploymentPlatform(): """Deeploy abstraction for a complete system, including at least a host core capable of memory allocation @@ -2399,6 +2465,16 @@ def __init__(self, engines: List[DeploymentEngine], variableBuffer: Type[Variabl self.StructBuffer = structBuffer self.TransientBuffer = transientBuffer + def __repr__(self) -> str: + retStr = f"{self.__class__.__name__}(" + retStr += f"engines={[e.name for e in self.engines]}, " + retStr += f"variableBuffer={self.VariableBuffer.__name__}, " + retStr += f"constantBuffer={self.ConstantBuffer.__name__}, " + retStr += f"structBuffer={self.StructBuffer.__name__}, " + retStr += f"transientBuffer={self.TransientBuffer.__name__}" + retStr += ")" + return retStr + class NetworkContainer(): """Deeploy abstraction for containing the information needed to describe a complete neural network to be deployed @@ -2442,6 +2518,7 @@ def __init__(self, self.ctxt.hoistConstant(x.attrs['value'], x.outputs[0].name, None) self.inputTypes = inputTypes + self.name = name self.ctxt = NetworkContext(variableBuffer = self.Platform.VariableBuffer, constantBuffer = self.Platform.ConstantBuffer, @@ -2453,6 +2530,9 @@ def __init__(self, self.bound = False self.transformed = False + def __repr__(self) -> str: + return f"{self.__class__.__name__}(name='{self.name}', platform={self.Platform.__class__.__name__}, inputTypes={ [v.typeName for k, v in self.inputTypes.items()]}, scheduler={self.scheduler.__name__})" + # Don't override this def _createIOBindings(self, ctxt: NetworkContext, graph: gs.Graph): @@ -2560,17 +2640,20 @@ def _bindLayers(self): for node in flatSchedule: layer = self._mapNode(node) if isinstance(layer, ONNXLayer): + log.debug(f" {SUCCESS_MARK} Bind {node.name} to layer {layer.__class__.__name__}") self.layerBinding[layer.node.name] = layer def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, default_channels_first: bool) -> Tuple[NetworkContext, bool]: - newCtxt, parsePass = node.parse(ctxt.copy(), default_channels_first) if not parsePass: return ctxt, False - newCtxt, LayerBindSuccess = node.typeCheck(newCtxt) + return newCtxt, True + + def _typeCheckNode(self, node: ONNXLayer, ctxt: NetworkContext) -> Tuple[NetworkContext, bool]: + newCtxt, LayerBindSuccess = node.typeCheck(ctxt) if not LayerBindSuccess: return ctxt, False @@ -2605,8 +2688,10 @@ def parse(self, default_channels_first: bool = True) -> bool: structBuffer = self.Platform.StructBuffer, transientBuffer = self.Platform.TransientBuffer) + log.debug(" - Create IO Bindings") self.ctxt = self._createIOBindings(self.ctxt, self.graph) + log.debug(" - Bind Nodes to Layers") self._bindLayers() ctxt = self.ctxt.copy() @@ -2617,15 +2702,33 @@ def parse(self, default_channels_first: bool = True) -> bool: deepestIdx = 0 + log.debug(" - Parse and Type Check Network") + start_time = time.perf_counter() + + iteration_main = 0 + iteration_sub = 0 + iteration_tot = 0 while (idx < len(scheduledLayerList)): currentLayer = scheduledLayerList[idx] + # Log current exploration state + if idx == 0: + iteration_main += 1 + iteration_tot += 1 + iteration_sub = 0 + log.debug(31 * "-" + f" MAIN ITERATION {iteration_main:<2} " + 31 * "-") + + log.debug(f"[Layer {idx}] Trying '{currentLayer.node.name}' (op: {currentLayer.node.op})") + stCtxt = copy.deepcopy(ctxt) newCtxt, parseSuccess = self._parseNode(currentLayer, ctxt, default_channels_first) + typeCheckSuccess = False if parseSuccess: + newCtxt, typeCheckSuccess = self._typeCheckNode(currentLayer, newCtxt) + if parseSuccess and typeCheckSuccess: # SCHEREMO: Continue depth-first exploration ctxtStack.append(stCtxt) ctxt = newCtxt @@ -2635,15 +2738,21 @@ def parse(self, default_channels_first: bool = True) -> bool: deepestCtxt = stCtxt else: - # SCHEREMO: Rollback one step - # SCHEREMO: If we can't find a mapping for the root, we must exit if idx == 0: deepestLayer = scheduledLayerList[deepestIdx] deepestNodeName = deepestLayer.node.name + log.debug("-" * 80) + log.error("💥 PARSING FAILED - Backtracking exhausted at root!") + log.error("=" * 80) + log.error(f"🔠Diagnosis:") + log.error(f" - Deepest successful exploration: Layer {deepestIdx} '{deepestNodeName}'") + log.error( + f" - Deepest layer available mappers: {[type(x.parser).__name__ for x in deepestLayer.maps]}") + log.error("=" * 80) raise RuntimeError( - f'Did not find adequate mapping for graph! Explored until layer {deepestLayer} of node {deepestNodeName} Candidates: {[type(x.parser).__name__ for x in deepestLayer.maps]}. Exhausted backtracking.' - ) + f'Did not find adequate mapping for graph! Explored until layer {deepestLayer.__class__.__name__} of node {deepestNodeName}' + f'Candidates: {[type(x.parser).__name__ for x in deepestLayer.maps]}. Exhausted backtracking.') previousLayer = scheduledLayerList[idx - 1] ctxt = ctxtStack.pop() @@ -2657,8 +2766,17 @@ def parse(self, default_channels_first: bool = True) -> bool: else: previousLayer.mapper.discardCurrentBinder() + # SCHEREMO: Rollback one step idx = idx - 1 - + if idx != 0: + iteration_sub += 1 + iteration_tot += 1 + log.debug(31 * "-" + f" SUB ITERATION {iteration_main}.{iteration_sub:<2} " + 31 * "-") + + end_time = time.perf_counter() + log.info( + f" {SUCCESS_MARK} Parsed network with {len(self.layerBinding)} layers after {iteration_tot} iterations in {(end_time-start_time)*1E3:.3f} ms" + ) self.ctxt = ctxt self.parsed = True return True @@ -2685,6 +2803,7 @@ def bind(self) -> bool: newCtxt = self.ctxt.copy() NetworkBindSuccess = True + log.info("- Map Layers to Bindings") for name, layer in self.layerBinding.items(): newCtxt, LayerBindSuccess = layer.bind(newCtxt) @@ -2693,6 +2812,8 @@ def bind(self) -> bool: if not NetworkBindSuccess: raise RuntimeError(f'Could not find a valid binding for the graph') + log.debug(f" {SUCCESS_MARK} Mapped {layer.node.name} to {layer.mapper.binder}") + self.bound = True self.ctxt = newCtxt @@ -2846,8 +2967,7 @@ def generateIOBufferInitializationCode(self) -> str: def worstCaseBufferSize(self): """Return the worst-case buffer size occupied by the network implementaiton """ - # WIESEP: There is no reasonable value for a worst case buffer size without tiling - raise NotImplementedError("Worst case buffer size is not known or not implemented!") + return self.ctxt._maxDynamicSize # Don't override this def generateBufferInitializationCode(self) -> str: @@ -2997,54 +3117,6 @@ def generateEngineInitializationCode(self) -> str: """ return ("\n").join([engine.initCode for engine in self.Platform.engines]) - # Don't override this - Returns parameter size in bytes - def getParameterSize(self) -> int: - """Return the BYTE size of all static network parameters (weights, biases, parameters,...) - - Returns - ------- - int - Size of all network parameters - - Raises - ------ - RuntimeError - Raises a RuntimeError if network is not parsed and bound - - - """ - if not self.parsed or not self.bound: - raise RuntimeError('You need to parse and bind the network before getting RAM Size!') - - size = 0 - for _buffer in self.ctxt.globalObjects.values(): - # We do not count structs for now, since they are not properly modeled - if isinstance(_buffer, ConstantBuffer) and _buffer._deploy: - size += int((np.prod(_buffer.shape) * _buffer._type.typeWidth // 8)) - - return size - - # Don't override this - Returns worst case layer and buffering size in bytes - def getTotalSize(self) -> int: - """Returns total size of the network, consisting of all parameters and intermediate buffer size - - Returns - ------- - int - Total network size - - Raises - ------ - RuntimeError - Raises a RuntimeError if network is not parsed and bound - - - """ - if not self.parsed or not self.bound: - raise RuntimeError('You need to parse and bind the network before getting RAM Size!') - - return self.getParameterSize() + self.worstCaseBufferSize - def numberOfOps(self, verbose: bool) -> int: """Returns the total number of operations per network inference @@ -3073,7 +3145,8 @@ def numberOfOps(self, verbose: bool) -> int: nodeOps = i.mapper.parser.operatorRepresentation['nodeOps'] totalSum += nodeOps if verbose: - print("Layer " + str(i.node.name) + str("\nNumber of operations: \t\t") + str("%12s\n" % nodeOps)) + log.info(f"Layer '{i.node.name}'") + log.info(f" Number of Operations : {nodeOps}") return totalSum # Don't override this @@ -3203,6 +3276,10 @@ def __init__(self, self.prepared = False + def __repr__(self): + return super().__repr__( + ) + f" (loweringOptimizer: {self.loweringOptimizer.name}, default_channels_first: {self.default_channels_first})" + # Don't override this def lower(self, graph: gs.Graph) -> gs.Graph: """Apply the lowering optimize @@ -3355,10 +3432,20 @@ def frontEnd(self): """API hook to prepare the graph to be deployed and build the initial NetworkContext """ + + log.info(80 * "=") + log.info("Deeploy FrontEnd") + log.info(80 * "=") + + log.info("- Apply Preprocessing") + + log.debug(" - Remove Identity Nodes") self._removeIdentityNodes() + log.debug(" - Mangle Tensor Names") self._mangleTensorNames() + log.debug(" - Mangle Node Names") self._mangleNodeNames() # Rename graph inputs and outputs: @@ -3367,24 +3454,32 @@ def frontEnd(self): for idx, outputNode in enumerate(self.graph.outputs): outputNode.name = "output_" + str(idx) + log.debug(" - Sanitize Graph Names") self._sanitizeGraphNames(self.graph) + log.debug(" - Remove Empty Inputs") self._removeEmptyInputs(self.graph) + log.debug(" - Duplicate Constants") self._duplicateConstants(self.graph) + log.debug(" - Constant Folding") self._foldConstants(self.graph) + log.info(f"> Export State to {_middlewarePreLoweringFilename}[.onnx|.pkl]") self.exportDeeployState(self.deeployStateDir, _middlewarePreLoweringFilename) + log.info("- Perform Graph Lowering") self.graph = self.lower(self.graph) # This lowers the graph to a deployable format + log.info(f"> Export State {_middlewarePostLoweringFilename}[.onnx|.pkl]") self.exportDeeployState(self.deeployStateDir, _middlewarePostLoweringFilename) + log.info("- Perform Graph Parsing") try: self.parse(self.default_channels_first) # This reparses the lowered graph except Exception as e: - print("Error during parsing! Exporting deeploy state!") + log.error(f"Error during parsing! Exporting deeploy state {_backendPostBindingFilename}[.onnx|.pkl]!") self.exportDeeployState(self.deeployStateDir, _backendPostBindingFilename) raise e @@ -3392,13 +3487,19 @@ def frontEnd(self): def midEnd(self): """API hook to be used after finalizing kernel selection; hoist transient buffers, and perform low-level code optimizations (e.g. tiling and static memory allocation) """ + log.info(80 * "=") + log.info("Deeploy MidEnd") + log.info(80 * "=") try: self.bind() except Exception as e: - print("Error during binding! Exporting deeploy state!") + log.error("Error during binding! Exporting deeploy state!") self.exportDeeployState(self.deeployStateDir, _backendPostBindingFilename) raise e + log.info(f"> Export State {_backendPostParsingFilename}[.onnx|.pkl]") + self.exportDeeployState(self.deeployStateDir, _backendPostParsingFilename) + # Don't override this unless you know what you are doin def backEnd(self, verbose: CodeGenVerbosity = _NoVerbosity): """API hook to generate code once kernel implementations are picked and tiling, memory allocation, and other low-level optimizations have been done. @@ -3409,11 +3510,14 @@ def backEnd(self, verbose: CodeGenVerbosity = _NoVerbosity): Control verbosity of generated code """ + log.info(80 * "=") + log.info("Deeploy BackEnd") + log.info(80 * "=") - self.exportDeeployState(self.deeployStateDir, _backendPostParsingFilename) - + log.info("- Performing code transformations and optimization...") self.codeTransform(verbose) + log.info(f"> Export State {_backendPostBindingFilename}[.onnx|.pkl]") self.exportDeeployState(self.deeployStateDir, _backendPostBindingFilename) # Don't override this @@ -3427,15 +3531,66 @@ def prepare(self, verbose: CodeGenVerbosity = _NoVerbosity): """ self.frontEnd() + self.midEnd() + self.backEnd(verbose = verbose) self.prepared = True + def _printInputOutputSummary(self): + log.info("Input:") + for buf in self.inputs(): + log.info(f" - '{buf.name}': Type: {buf._type.referencedType.typeName}") + + log.info('Output:') + for buf in self.outputs(): + log.info(f" - '{buf.name}': Type: {buf._type.referencedType.typeName}") + + def _printMemorySummary(self): + log.info("") + log.info("Memory Usage Report:") + log.info(f" Level Total (bytes) (Static + Dynamic) ") + log.info(" " + "-" * 60) + + _worstCaseBufferSize = self.worstCaseBufferSize + if len(_worstCaseBufferSize) == 0: + _worstCaseBufferSize = {"None": 0} + + for level, dynamicSize in _worstCaseBufferSize.items(): + staticSize = 0 + for _buffer in self.ctxt.globalObjects.values(): + # We do not count structs for now, since they are not properly modeled + if isinstance(_buffer, ConstantBuffer) or (isinstance(_buffer, VariableBuffer) and _buffer._deploy): + # SCHEREMO: We only + if (hasattr(_buffer, "_memoryLevel") and _buffer._memoryLevel == level) or level == "None": + staticSize += int((np.prod(_buffer.shape) * _buffer._type.referencedType.typeWidth // 8)) + else: + log.warning(f"Buffer {_buffer.name} does not have a valid memory level") + + total = staticSize + dynamicSize + + log.info(f" {level:<22} {total:8,d} " + f"({staticSize:6,d} + {dynamicSize:7,d}) ") + def generateFunction(self, verbose: CodeGenVerbosity = _NoVerbosity) -> str: """Helper function to prepare deployment and return generated function code """ + if not self.prepared: self.prepare(verbose = verbose) + log.info("=" * 80) + log.info("Deeploy Code Generation") + log.info("=" * 80) + + self._printInputOutputSummary() + + num_ops = self.numberOfOps(verbose = True) + log.info("-" * 80) + + log.info(f"Number of Ops. : {num_ops}") + + self._printMemorySummary() + return self.generateInferenceCode() diff --git a/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py b/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py index a32875bc72..eb7a7b791f 100644 --- a/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py +++ b/Deeploy/FutureExtension/Bindings/AutoFutureBinding.py @@ -7,6 +7,7 @@ from Deeploy.DeeployTypes import CodeTransformation, NetworkContext, NodeTemplate, NodeTypeChecker from Deeploy.FutureExtension.Bindings.FutureBinding import FutureBinding from Deeploy.FutureExtension.Future import Future +from Deeploy.Logging import DEFAULT_LOGGER as log class AutoFutureBinding(FutureBinding): @@ -21,7 +22,7 @@ def __init__(self, futureOutputs = [idx for idx, output in enumerate(self.typeChecker.output_types) if issubclass(output, Future)] if len(futureOutputs) > 1: - raise Exception(f"{self} assigns more than one future output!") + raise ValueError(f"{self} assigns more than one future output!") if len(futureOutputs) == 1: self.stateReferenceType = self.typeChecker.output_types[futureOutputs[0]].stateReferenceType @@ -31,7 +32,7 @@ def __init__(self, def assignStateReferenceElement(self, ctxt) -> NetworkContext: if len(self.futureOutputs) > 1: - raise Exception(f"{self} assigns more than one future output!") + raise ValueError(f"{self} assigns more than one future output!") if len(self.futureOutputs) == 0: return ctxt @@ -48,7 +49,7 @@ def assignStateReferenceElement(self, ctxt) -> NetworkContext: stateElementCandidates.append(reference) if len(stateElementCandidates) == 1: - print(f"WARNING: Automagically assigning state Element of {self}") + log.warning(f"Automagically assigning state Element of {self}") for key, value in operatorRepresentation.items(): if type(value) == str and (ctxt.is_local(value) or ctxt.is_global(value)): reference = ctxt.lookup(value) @@ -56,6 +57,6 @@ def assignStateReferenceElement(self, ctxt) -> NetworkContext: reference._instance.assignStateReference(stateElementCandidates[0], ctxt) else: - raise Exception(f"Can't assign a unique state element to {self} automagically!") + raise ValueError(f"Can't assign a unique state element to {self} automagically!") return ctxt diff --git a/Deeploy/Logging.py b/Deeploy/Logging.py new file mode 100644 index 0000000000..2220e0351c --- /dev/null +++ b/Deeploy/Logging.py @@ -0,0 +1,62 @@ +# ---------------------------------------------------------------------- +# +# File: Logging.py +# +# Last edited: 22.08.2025 +# +# Copyright (C) 2025, ETH Zurich and University of Bologna. +# +# Author: +# - Philip Wiese, ETH Zurich +# +# ---------------------------------------------------------------------- +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Setup logging +import logging +from enum import Enum + +import coloredlogs + + +class AnsiColorCode(Enum): + LigthBlue = "\033[94m" + Green = "\033[92m" + Yellow = "\033[93m" + Red = "\033[91m" + Magenta = "\033[95m" + Reset = "\033[0m" + + def __str__(self) -> str: + return self.value + + +def color(msg: str, color: AnsiColorCode) -> str: + return f"{color}{msg}{AnsiColorCode.Reset}" + + +SUCCESS_MARK = color("✔", AnsiColorCode.Green) +FAILURE_MARK = color("✘", AnsiColorCode.Red) + +CONSOLE_LOG_FORMAT = "[%(name)s] %(message)s" +FILE_LOG_FORMAT = "[%(name)s] [%(module)-15s] %(message)s" +DETAILED_FILE_LOG_FORMAT = "[%(levelname)s] [%(name)s] [%(pathname)s:%(lineno)d] %(message)s" + +DEFAULT_LOGGER = logging.getLogger("Deeploy") +DEFAULT_FMT = CONSOLE_LOG_FORMAT + +# Install default logging if not already installed +if not DEFAULT_LOGGER.handlers: + coloredlogs.install(level = 'INFO', logger = DEFAULT_LOGGER, fmt = DEFAULT_FMT) diff --git a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py index 9baeff2396..46aa144135 100644 --- a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py +++ b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py @@ -13,6 +13,7 @@ from Deeploy.DeeployTypes import CodeGenVerbosity, ConstantBuffer, DeploymentEngine, DeploymentPlatform, \ NetworkContext, NetworkDeployer, NetworkOptimizationPass, NetworkOptimizer, ONNXLayer, Schedule, StructBuffer, \ TopologyOptimizer, TransientBuffer, VariableBuffer, _NoVerbosity +from Deeploy.Logging import DEFAULT_LOGGER as log from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.OptimizationPasses.MemoryLevelAnnotationPasses import AnnotateDefaultMemoryLevel @@ -74,7 +75,37 @@ def lookup(self, nodeName: str, tensorName: str) -> str: return self._mapping[nodeName, tensorName] -class MemoryLevelAwareDeployer(NetworkDeployer): +class MemorySummaryMixin: + + def _printMemorySummary(self): + log.info("") + log.info("Memory Usage Report:") + log.info(f" {'Level':<14} {'Capacity (bytes)':>10} {'Total':>10} ( Static + Dynamic ) (Usage )") + log.info(" " + "-" * 78) + + for level, dynamicSize in self.worstCaseBufferSize.items(): + staticSize = 0 + for _buffer in self.ctxt.globalObjects.values(): + # We do not count structs for now, since they are not properly modeled + if isinstance(_buffer, ConstantBuffer) and getattr(_buffer, "_deploy", False): + if (hasattr(_buffer, "_memoryLevel") and _buffer._memoryLevel == level) or level in ("None", None): + staticSize += _buffer.sizeInBytes() + + total = staticSize + dynamicSize + memLevels = self.Platform.memoryHierarchy.memoryLevels + memLevel = memLevels.get(level, None) + if memLevel is None or getattr(memLevel, "size", None) is None: + log.info(f" {str(level):<20} {'N/A':>10} {total:10,d} " + f"({staticSize:10,d} + {dynamicSize:10,d}) " + f"({'N/A':>5})") + else: + capacity = memLevel.size + log.info(f" {str(level):<20} {capacity:10,} {total:10,d} " + f"({staticSize:10,d} + {dynamicSize:10,d}) " + f"({total / capacity * 100:5.1f}%)") + + +class MemoryLevelAwareDeployer(NetworkDeployer, MemorySummaryMixin): def __init__(self, graph: gs.Graph, @@ -100,18 +131,14 @@ def getTargetMemoryLevelMapping(self) -> TargetMemoryLevelMapping: def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, default_channels_first: bool) -> Tuple[NetworkContext, bool]: - newCtxt, parsePass = node.parse(ctxt.copy(), default_channels_first) + newCtxt, parsePass = super()._parseNode(node, ctxt, default_channels_first) if not parsePass: return ctxt, False newCtxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(newCtxt, self.graph) - newCtxt, LayerBindSuccess = node.typeCheck(newCtxt) - if not LayerBindSuccess: - return ctxt, False - - return newCtxt, True + return newCtxt, parsePass def bind(self): @@ -119,6 +146,7 @@ def bind(self): if not ret: return False + log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) @@ -129,7 +157,7 @@ def codeTransform(self, verbose: CodeGenVerbosity = _NoVerbosity): super().codeTransform(verbose) -class MemoryLevelAwareSignPropDeployer(SignPropDeployer): +class MemoryLevelAwareSignPropDeployer(SignPropDeployer, MemorySummaryMixin): def __init__(self, graph: gs.Graph, @@ -175,6 +203,7 @@ def bind(self): if not ret: return False + log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) @@ -185,7 +214,7 @@ def codeTransform(self, verbose: CodeGenVerbosity = _NoVerbosity): super().codeTransform(verbose) -class MemoryDeployerWrapper(NetworkDeployerWrapper): +class MemoryDeployerWrapper(NetworkDeployerWrapper, MemorySummaryMixin): def __init__(self, deployer: NetworkDeployer, memoryLevelAnnotationPasses: List[NetworkOptimizationPass] = []): super().__init__(deployer) @@ -222,6 +251,7 @@ def bind(self): if not ret: return False + log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) diff --git a/Deeploy/Targets/Chimera/Platform.py b/Deeploy/Targets/Chimera/Platform.py index 0244502fd2..0906ddfae0 100644 --- a/Deeploy/Targets/Chimera/Platform.py +++ b/Deeploy/Targets/Chimera/Platform.py @@ -47,9 +47,11 @@ class ChimeraStructBuffer(StructBuffer): deallocTemplate = NodeTemplate("") -ChimeraOptimizer = TopologyOptimizer([ - # JUNGVI: Nothing for now -]) +ChimeraOptimizer = TopologyOptimizer( + [ + # JUNGVI: Nothing for now + ], + name = "ChimeraOptimizer") _includeList = [ "uart.h", diff --git a/Deeploy/Targets/CortexM/Platform.py b/Deeploy/Targets/CortexM/Platform.py index f788baaf18..25caeed60f 100644 --- a/Deeploy/Targets/CortexM/Platform.py +++ b/Deeploy/Targets/CortexM/Platform.py @@ -123,18 +123,20 @@ class CMSISStructBuffer(StructBuffer): # ExtractPaddingFromConvPass(),ExtractPaddingFromPoolPass(), -CMSISOptimizer = TopologyOptimizer([ - IntegerDivRequantMergePass(), - iGELURequantMergePass(), - LinearAttentionAlignmentPass(), - MHSAAlignmentPass(), - MergeConstAddAndRequantPass(), - ConvRequantMergePass(), - GEMMRequantMergePass(), - MatMulRequantMergePass(), - # DebugPass("Conv", position='before'), - # DebugPass("Pad", position='after'), -]) +CMSISOptimizer = TopologyOptimizer( + [ + IntegerDivRequantMergePass(), + iGELURequantMergePass(), + LinearAttentionAlignmentPass(), + MHSAAlignmentPass(), + MergeConstAddAndRequantPass(), + ConvRequantMergePass(), + GEMMRequantMergePass(), + MatMulRequantMergePass(), + # DebugPass("Conv", position='before'), + # DebugPass("Pad", position='after'), + ], + name = "CMSISOptimizer") includeList = ["arm_nnfunctions.h", "DeeployMath.h"] diff --git a/Deeploy/Targets/Generic/Platform.py b/Deeploy/Targets/Generic/Platform.py index 0a620f9eb2..c09b89df96 100644 --- a/Deeploy/Targets/Generic/Platform.py +++ b/Deeploy/Targets/Generic/Platform.py @@ -142,17 +142,19 @@ class GenericStructBuffer(StructBuffer): deallocTemplate = NodeTemplate("") -GenericOptimizer = TopologyOptimizer([ - QuantPatternPass(), - DequantPatternPass(), - iGELURequantMergePass(), - MatMulAddMergePass(), - MergeConstAddAndRequantPass(), - ExtractPaddingFromConvPass(), - ExtractPaddingFromPoolPass(), - RemoveEmptyConvBiasPass(), - # DebugPrintPass(r'.*[Mm]at[Mm]ul.*', position = 'after'), -]) +GenericOptimizer = TopologyOptimizer( + [ + QuantPatternPass(), + DequantPatternPass(), + iGELURequantMergePass(), + MatMulAddMergePass(), + MergeConstAddAndRequantPass(), + ExtractPaddingFromConvPass(), + ExtractPaddingFromPoolPass(), + RemoveEmptyConvBiasPass(), + # DebugPrintPass(r'.*[Mm]at[Mm]ul.*', position = 'after'), + ], + name = "GenericOptimizer") includeList = ["DeeployBasicMath.h"] diff --git a/Deeploy/Targets/MemPool/Platform.py b/Deeploy/Targets/MemPool/Platform.py index 3302d1eb12..4f1a982988 100644 --- a/Deeploy/Targets/MemPool/Platform.py +++ b/Deeploy/Targets/MemPool/Platform.py @@ -163,22 +163,24 @@ class MemPoolStructBuffer(StructBuffer): deallocTemplate = NodeTemplate("") -MemPoolOptimizer = TopologyOptimizer([ - MemPoolFuseMHSAPass(H = 8, bias = False, preSoftMaxRQ = True, integerDiv = False), - MemPoolFuseMHSAPass(H = 1, bias = False, preSoftMaxRQ = True, integerDiv = False), - MemPoolFuseMHSAPass(H = -1, bias = False, preSoftMaxRQ = True, integerDiv = False), - MemPoolFuseMHSAPass(H = -1, bias = True, preSoftMaxRQ = True, integerDiv = False), - MemPoolSplitMHSAPass(), - iGELURequantMergePass(), - MatMulAddMergePass(), - SplitAddPass(), - MergeConstAddAndRequantPass(), - MemPoolMatMulRequantMergePass(), - MemPoolGEMMRequantMergePass(), - ExtractPaddingFromConvPass(), - ExtractPaddingFromPoolPass(), - # DebugPrintPass(r'.*[Mm]at[Mm]ul.*', position = 'after'), -]) +MemPoolOptimizer = TopologyOptimizer( + [ + MemPoolFuseMHSAPass(H = 8, bias = False, preSoftMaxRQ = True, integerDiv = False), + MemPoolFuseMHSAPass(H = 1, bias = False, preSoftMaxRQ = True, integerDiv = False), + MemPoolFuseMHSAPass(H = -1, bias = False, preSoftMaxRQ = True, integerDiv = False), + MemPoolFuseMHSAPass(H = -1, bias = True, preSoftMaxRQ = True, integerDiv = False), + MemPoolSplitMHSAPass(), + iGELURequantMergePass(), + MatMulAddMergePass(), + SplitAddPass(), + MergeConstAddAndRequantPass(), + MemPoolMatMulRequantMergePass(), + MemPoolGEMMRequantMergePass(), + ExtractPaddingFromConvPass(), + ExtractPaddingFromPoolPass(), + # DebugPrintPass(r'.*[Mm]at[Mm]ul.*', position = 'after'), + ], + name = "MemPoolOptimizer") includeList = ["DeeployMath.h", "runtime.h", "synchronization.h"] diff --git a/Deeploy/Targets/Neureka/Platform.py b/Deeploy/Targets/Neureka/Platform.py index 04e92468d4..e83f7f20f4 100644 --- a/Deeploy/Targets/Neureka/Platform.py +++ b/Deeploy/Targets/Neureka/Platform.py @@ -18,7 +18,7 @@ NeurekaOptimizer = TopologyOptimizer([ *PULPOptimizer.passes, RequantizedGemmToPwPass(), -]) +], name = "NeurekaOptimizer") class NeurekaConstantBuffer(ConstantBuffer): diff --git a/Deeploy/Targets/PULPOpen/Platform.py b/Deeploy/Targets/PULPOpen/Platform.py index dce02b2efe..99c1c93351 100644 --- a/Deeploy/Targets/PULPOpen/Platform.py +++ b/Deeploy/Targets/PULPOpen/Platform.py @@ -226,7 +226,8 @@ class PULPStructBuffer(StructBuffer): PULPGEMMRequantMergePass(), PULPMatMulRequantMergePass(), PULPAddRequantMergePass() -]) +], + name = "PULPOptimizer") # SCHEREMO: stdint is included before pulp_nn_kernels.h because it is supposed to be included in there, but isn't... _includeList = [ diff --git a/Deeploy/Targets/Snitch/Platform.py b/Deeploy/Targets/Snitch/Platform.py index 1a9e714081..d62d1c3802 100644 --- a/Deeploy/Targets/Snitch/Platform.py +++ b/Deeploy/Targets/Snitch/Platform.py @@ -138,7 +138,8 @@ class SnitchStructBuffer(StructBuffer): MergeConstAddAndRequantPass(), AddRequantMergePass(), GEMMRequantMergePass(), -]) +], + name = "SnitchOptimizer") _includeList = [ "snrt.h", diff --git a/Deeploy/Targets/SoftHier/Platform.py b/Deeploy/Targets/SoftHier/Platform.py index 8c0c0f6e5e..42265bbd81 100644 --- a/Deeploy/Targets/SoftHier/Platform.py +++ b/Deeploy/Targets/SoftHier/Platform.py @@ -91,7 +91,7 @@ class SoftHierStructBuffer(StructBuffer): deallocTemplate = NodeTemplate("") -SoftHierOptimizer = TopologyOptimizer([]) +SoftHierOptimizer = TopologyOptimizer([], name = "SoftHierOptimizer") includeList = ["DeeployBasicMath.h", "flex_alloc_api.h"] diff --git a/Deeploy/TilingExtension/MemoryScheduler.py b/Deeploy/TilingExtension/MemoryScheduler.py index 71e4ebea88..e46f50e6f7 100644 --- a/Deeploy/TilingExtension/MemoryScheduler.py +++ b/Deeploy/TilingExtension/MemoryScheduler.py @@ -553,7 +553,7 @@ def constraintTileBuffersWithOverlappingLifetime(self, tilerModel: TilerModel, c if memoryLevel.name == infoDict['memoryLevel']: sumExpr += infoDict['sizeVar'] * infoDict['typeWidthFactor'] * infoDict['multiBufferCoeff'] if sumExpr != 0: - tilerModel.addConstraint(sumExpr + constantTensorOffset <= memoryLevel.size) + tilerModel.addConstraint(sumExpr + constantTensorOffset, memoryLevel = memoryLevel) def getSymbolicCostName(self, patternIdx: int, memoryLevel: str) -> str: stringSuffix = self._stringSuffix + f"_{memoryLevel}" diff --git a/Deeploy/TilingExtension/TilerExtension.py b/Deeploy/TilingExtension/TilerExtension.py index dedb1d1d1b..bdae0fbdcf 100644 --- a/Deeploy/TilingExtension/TilerExtension.py +++ b/Deeploy/TilingExtension/TilerExtension.py @@ -23,6 +23,8 @@ from Deeploy.CommonExtensions.NetworkDeployers.NetworkDeployerWrapper import NetworkDeployerWrapper from Deeploy.DeeployTypes import ConstantBuffer, NetworkContext, NodeBinding, NodeTemplate, ONNXLayer, Schedule, \ SubGraph, TransientBuffer +from Deeploy.Logging import DEFAULT_LOGGER as log +from Deeploy.Logging import SUCCESS_MARK from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryDeployerWrapper, \ MemoryLevelAwareDeployer, MemoryPlatform, MemoryPlatformWrapper, TargetMemoryLevelMapping @@ -105,6 +107,12 @@ def plotSingleMemoryLevel(memoryLevel: MemoryLevel): for memoryMapStep in memoryMap[memoryLevel.name]: for buffer in memoryMapStep: + if not hasattr(buffer, "_addrSpace") or buffer._addrSpace is None: + log.warning( + f"Buffer {buffer.name} has no address space assigned, skipping it in the memory allocation plot." + ) + continue + fig.add_trace( go.Scatter(x = [ buffer._lifetime[0] - 0.5, buffer._lifetime[0] - 0.5, buffer._lifetime[1] + 0.5, @@ -271,8 +279,8 @@ def minimalloc(self, memoryMap, ctxt, nodeMemoryConstraint, capacity: int, memor text = True) if minimallocOutput.returncode != 0: - print( - f"\033[91mError: Memory allocator failed with return code {minimallocOutput.returncode} at memory level {memoryLevel} with capacity of {capacity} bytes \033[0m" + log.error( + f"Memory allocator failed with return code {minimallocOutput.returncode} at memory level {memoryLevel} with capacity of {capacity} bytes!" ) raise subprocess.CalledProcessError(minimallocOutput.returncode, " ".join(minimallocOutput.args)) @@ -292,6 +300,7 @@ def computeTilingSchedule(self, ctxt: NetworkContext) -> TilingSolution: tilingSolution = self._getTilingSolution(self.tilerModel, ctxt, collector, self.symbolicMemoryConstraints) if not self.memoryAllocStrategy == "MiniMalloc": assert self.tilerModel is not None + log.debug(" - Extract Memory Allocation") self.innerMemoryScheduler.annotateSolution(ctxt, self.tilerModel) self.outerMemoryScheduler.annotateSolution(ctxt, self.tilerModel) return tilingSolution @@ -303,6 +312,7 @@ def computeMemoryMap(self, ctxt: NetworkContext, tilingSolution: TilingSolution) memoryMap[key] = [*self.innerMemoryScheduler.memoryMap[key], *self.outerMemoryScheduler.memoryMap[key]] if self.memoryAllocStrategy == "MiniMalloc": + log.debug(" - Solve Memory Allocation with MiniMalloc") for memoryLevel in memoryMap.keys(): constantTensorOffset = self.outerMemoryScheduler.getConstantTensorOffset(ctxt, memoryLevel) if memoryLevel == self.memoryHierarchy._defaultMemoryLevel.name: @@ -315,8 +325,7 @@ def computeMemoryMap(self, ctxt: NetworkContext, tilingSolution: TilingSolution) memoryMap[memoryLevel][idx] = self.minimalloc( memMap, ctxt, tilingSolution[idx].nodeConstraints[0], self.memoryHierarchy.memoryLevels[memoryLevel].size - constantTensorOffset, memoryLevel) - - print(f"\033[92mMemory allocation sucessful!\033[0m") + log.info(f" {SUCCESS_MARK} Memory allocation successful!") return memoryMap @@ -942,13 +951,7 @@ def __init__(self, deployer: Union[MemoryLevelAwareDeployer, MemoryDeployerWrapp @property def worstCaseBufferSize(self): - maxAddr: Dict[str, int] = self.tiler.worstCaseBufferSize - - # WIESEP: Memory map form tiler does not include inputs and outputs - for node in (self.inputs() + self.outputs()): - maxAddr[node._memoryLevel] += np.prod(node.shape) * node._type.referencedType.typeWidth // 8 - - return maxAddr + return self.tiler.worstCaseBufferSize def tile(self, tilingSolution: Optional[TilingSolution] = None, memoryMap: Optional[MemoryMap] = None): assert (tilingSolution is None and memoryMap is None) or (tilingSolution is not None and memoryMap is not None), \ @@ -964,6 +967,7 @@ def tile(self, tilingSolution: Optional[TilingSolution] = None, memoryMap: Optio self.ctxt, self.Platform.memoryHierarchy._defaultMemoryLevel.name ), "All tensors have to be in the default memory level when using MiniMalloc!" + log.debug(" - Setup Constraint Model") self.tiler.setupModel(ctxt = self.ctxt, schedule = schedule, layerBinding = self.layerBinding, @@ -974,15 +978,19 @@ def tile(self, tilingSolution: Optional[TilingSolution] = None, memoryMap: Optio assert tilingSolution is not None and memoryMap is not None + log.debug(" - Test Tiling Solution Correctness") self.tiler.testTilingSolutionCorrectness(tilingSolution) + log.debug(" - Annotate Memory Levels") self.tiler.annotateMemoryLevel(self.ctxt, tilingSolution, memoryMap) self.ctxt = self.tiler._convertCtxtToStaticSchedule(self.ctxt, memoryMap) if self.tiler.visualizeMemoryAlloc: + log.info(f" > Export Memory Allocation Visualization to {self.deeployStateDir}") self.tiler.plotMemoryAlloc(memoryMap, self.ctxt, self.deeployStateDir, self.Platform.memoryHierarchy) + log.debug(" - Test Memory Map Correctness") self.tiler.testMemoryMapCorrectness(memoryMap, self.graph, schedule) # SCHEREMO: Annotate execution block with solution @@ -995,9 +1003,25 @@ def bind(self): if not super().bind(): return False + log.info("- Performing Tiling and Memory Allocation") self.tile() return True + def _printMemorySummary(self): + log.info("") + log.info("Memory Usage Report:") + log.info(f" {'Level':<14} {'Capacity (bytes)':>10} {'Total':>10} ( Static + Dynamic ) (Usage )") + log.info(" " + "-" * 78) + + for level, dynamicSize in self.worstCaseBufferSize.items(): + staticSize = self.tiler.outerMemoryScheduler.getConstantTensorOffset(self.ctxt, level) + capacity = self.tiler.memoryHierarchy.memoryLevels[level].size + total = staticSize + dynamicSize + + log.info(f" {level:<20} {capacity:10,} {total:10,d} " + f"({staticSize:10,d} + {dynamicSize:10,d}) " + f"({total / capacity * 100:5.1f}%)") + def TilingReadyNodeBindings(nodeBindings: List[NodeBinding], tileConstraint: TileConstraint) -> List[NodeBinding]: ''' diff --git a/Deeploy/TilingExtension/TilerModel.py b/Deeploy/TilingExtension/TilerModel.py index 8fb1c5ba74..80f0191d76 100644 --- a/Deeploy/TilingExtension/TilerModel.py +++ b/Deeploy/TilingExtension/TilerModel.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 +import logging from dataclasses import dataclass from pprint import pformat from typing import Dict, List, Literal, Optional, Tuple, Union @@ -10,6 +11,7 @@ from ortools.constraint_solver.pywrapcp import IntExpr, IntVar, SolutionCollector, Solver from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation +from Deeploy.Logging import DEFAULT_LOGGER as log from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryLevel _COPYIDXSUFFIX = "_copyIdx_" @@ -102,6 +104,10 @@ def addConstraint(self, constraintExpression: IntExpr, memoryLevel: Optional[MemoryLevel] = None, strategy: Optional[AddConstraintStrategy] = None): + # Skip TrueConstraints + if constraintExpression.DebugString() == "TrueConstraint()": + return + if isinstance(strategy, PerformanceHint): if memoryLevel is None: self._performanceConstraints.append((strategy.priority, constraintExpression)) @@ -382,9 +388,13 @@ def _solveModel( timeLimit = self._model.TimeLimit(_SOLVERTIMEOUT) - log = self._model.SearchLog(1000000) + log.debug(" - Solve Constraint Model") - _ = self._model.Solve(decisionBuilder, [objective, collector, log, timeLimit]) + if log.getEffectiveLevel() <= logging.DEBUG: + searchLog = self._model.SearchLog(1000000) + _ = self._model.Solve(decisionBuilder, [objective, collector, searchLog, timeLimit]) + else: + _ = self._model.Solve(decisionBuilder, [objective, collector, None, timeLimit]) assert collector.SolutionCount() > 0, "Error in Tiler: No solution found" diff --git a/DeeployTest/generateNetwork.py b/DeeployTest/generateNetwork.py index 1aebd4a826..24f0638f21 100644 --- a/DeeployTest/generateNetwork.py +++ b/DeeployTest/generateNetwork.py @@ -18,13 +18,14 @@ from Deeploy.CommonExtensions.DataTypes import IntegerDataTypes from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.DebugPasses import EmulateCMSISRequantPass from Deeploy.DeeployTypes import _NoVerbosity +from Deeploy.Logging import DEFAULT_LOGGER as log from Deeploy.Targets.CortexM.Platform import CMSISPlatform from Deeploy.Targets.PULPOpen.Platform import PULPPlatform -_TEXT_ALIGN = 30 - def generateNetwork(args): + log.debug("Arguments: %s", args) + onnx_graph = onnx.load_model(f'{args.dir}/network.onnx') graph = gs.import_onnx(onnx_graph) @@ -86,6 +87,12 @@ def generateNetwork(args): inputTypes = {} inputOffsets = {} + log.debug(f"Platform: {platform} (sign: {signProp})") + + log.debug("Platform Engines:") + for engine in platform.engines: + log.debug(f" - {engine.name}: {engine}") + for index, (name, values) in enumerate(zip(inputs.files, test_inputs)): if np.prod(values.shape) == 0: continue @@ -105,9 +112,9 @@ def generateNetwork(args): # Suggest a smaller fitting type if possible fitting_types = [t for t in sorted(IntegerDataTypes, key = lambda x: x.typeWidth) if t.checkPromotion(vals)] if fitting_types and fitting_types[0] is not _type: - print(f"WARNING: Data spans [{int(vals.min())}, {int(vals.max())}], " - f"which would fit in '{fitting_types[0].typeName}', " - f"but user forced '{_type.typeName}'.") + log.warning(f"Data spans [{int(vals.min())}, {int(vals.max())}], " + f"which would fit in '{fitting_types[0].typeName}', " + f"but user forced '{_type.typeName}'.") _type = PointerClass(_type) else: @@ -120,6 +127,8 @@ def generateNetwork(args): deployer = mapDeployer(platform, graph, inputTypes, deeployStateDir = _DEEPLOYSTATEDIR, inputOffsets = inputOffsets) + log.debug(f"Deployer: {deployer}") + if not isinstance( platform, CMSISPlatform ) and not "simpleCNN" in args.dir and not "testRQMatMul" in args.dir and not "testRQGEMM" in args.dir: @@ -130,7 +139,7 @@ def generateNetwork(args): verbosityCfg.untiledProfiling = args.profileUntiled # Parse graph and infer output levels and signedness - _ = deployer.generateFunction(verbose = verbosityCfg) + _ = deployer.prepare(verbosityCfg) # Offset the input and output values if signprop if signProp: @@ -145,29 +154,6 @@ def generateNetwork(args): generateTestNetwork(deployer, test_inputs, test_outputs, args.dumpdir, verbosityCfg) - if args.verbose: - print() - print("=" * 80) - print("Output:") - for i in range(len(test_outputs)): - buffer = deployer.ctxt.lookup(f"output_{i}") - logLine = f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}" - if signProp: - logLine += f", nLevels: {buffer.nLevels}, Signed: {buffer._signed}" - print(logLine) - print('Input:') - for i in range(len(test_inputs)): - buffer = deployer.ctxt.lookup(f"input_{i}") - print( - f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}, Offset: {inputOffsets[buffer.name]}" - ) - print("=" * 80) - num_ops = deployer.numberOfOps(args.verbose) - print("=" * 80) - print() - print(f"{'Number of Ops:' :<{_TEXT_ALIGN}} {num_ops}") - print(f"{'Model Parameters: ' :<{_TEXT_ALIGN}} {deployer.getParameterSize()}") - if __name__ == '__main__': diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index 0714f78d7e..013f854daa 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 +import argparse import os import sys from collections import OrderedDict @@ -20,14 +21,13 @@ from Deeploy.DeeployTypes import CodeGenVerbosity, NetworkDeployer, ONNXLayer from Deeploy.EngineExtension.NetworkDeployers.EngineColoringDeployer import EngineColoringDeployerWrapper +from Deeploy.Logging import DEFAULT_LOGGER as log from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryDeployerWrapper from Deeploy.MemoryLevelExtension.OptimizationPasses.MemoryLevelAnnotationPasses import AnnotateDefaultMemoryLevel, \ AnnotateIOMemoryLevel, AnnotateNeurekaWeightMemoryLevel from Deeploy.TilingExtension.TilerExtension import TilerDeployerWrapper -_TEXT_ALIGN = 30 - # Mock of the Global Scheduler's inteface # Returns a list of list of nodes instead of simply a list @@ -55,7 +55,8 @@ def _filterSchedule(schedule: List[List[gs.Node]], layerBinding: 'OrderedDict[st def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTargetMemoryLevel: MemoryLevel, - defaultIoMemoryLevel: MemoryLevel, verbose: CodeGenVerbosity) -> Tuple[NetworkDeployer, bool]: + defaultIoMemoryLevel: MemoryLevel, verbose: CodeGenVerbosity, + args: argparse.Namespace) -> Tuple[NetworkDeployer, bool]: inputTypes = {} inputOffsets = {} @@ -192,12 +193,14 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg """) parser.add_argument('--profileTiling', action = "store_true") parser.add_argument('--plotMemAlloc', - action = 'store_false', + action = 'store_true', help = 'Turn on plotting of the memory allocation and save it in the deeployState folder\n') parser.set_defaults(shouldFail = False) args = parser.parse_args() + log.debug("Arguments: %s", args) + verbosityCfg = CodeGenVerbosity(None) if args.profileTiling: @@ -246,10 +249,19 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg memoryHierarchy, defaultTargetMemoryLevel = L1, defaultIoMemoryLevel = memoryHierarchy.memoryLevels[args.defaultMemLevel], - verbose = verbosityCfg) + verbose = verbosityCfg, + args = args) platform = deployer.Platform + log.debug(f"Platform: {platform} (sign: {signProp})") + + log.debug("Platform Engines:") + for engine in platform.engines: + log.debug(f" - {engine.name}: {engine}") + + log.debug(f"Deployer: {deployer}") + for index, num in enumerate(test_inputs): _type, offset = inferTypeAndOffset(num, signProp) inputTypes[f"input_{index}"] = _type @@ -265,7 +277,7 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg sys.exit(0) else: - _ = deployer.generateFunction(verbosityCfg) + _ = deployer.prepare(verbosityCfg) # Offset the input and output values if signprop if signProp: @@ -279,31 +291,3 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg values -= buffer.nLevels // 2 generateTestNetwork(deployer, test_inputs, test_outputs, args.dumpdir, verbosityCfg) - - if args.verbose: - print() - print("=" * 80) - print("Output:") - for i in range(len(test_outputs)): - buffer = deployer.ctxt.lookup(f"output_{i}") - logLine = f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}" - if signProp: - logLine += f", nLevels: {buffer.nLevels}, Signed: {buffer._signed}" - print(logLine) - print('Input:') - for i in range(len(test_inputs)): - buffer = deployer.ctxt.lookup(f"input_{i}") - print( - f" - '{buffer.name}': Type: {buffer._type.referencedType.typeName}, Offset: {inputOffsets[buffer.name]}" - ) - print("=" * 80) - num_ops = deployer.numberOfOps(args.verbose) - print("=" * 80) - print() - print(f"{'Number of Ops:' :<{_TEXT_ALIGN}} {num_ops}") - print('Worst Case Buffer Size:') - for level in deployer.worstCaseBufferSize.keys(): - print(f"{' ' + str(level) + ':' :<{_TEXT_ALIGN}} {deployer.worstCaseBufferSize[level]}") - print(f"{'Model Parameters: ' :<{_TEXT_ALIGN}} {deployer.getParameterSize()}") - - print("\033[92mCode Generation test ended, no memory violations!\033[0m") diff --git a/DeeployTest/testUtils/codeGenerate.py b/DeeployTest/testUtils/codeGenerate.py index 8addf6827b..878bc42014 100644 --- a/DeeployTest/testUtils/codeGenerate.py +++ b/DeeployTest/testUtils/codeGenerate.py @@ -73,6 +73,7 @@ def generateTestInputsHeader(deployer: NetworkDeployer, test_inputs: List) -> st retStr += f"void* testInputVector[{len(vectors)}] = {{" retStr += ", ".join(vectors) retStr += "};\n" + return retStr @@ -107,6 +108,7 @@ def generateTestOutputsHeader(deployer: NetworkDeployer, test_outputs: List[np.n retStr += f"void* testOutputVector[{len(test_outputs)}] = " + "{" retStr += ", ".join([f"testOutputVector{idx}" for idx, _ in enumerate(test_outputs)]) retStr += "};\n" + return retStr diff --git a/DeeployTest/testUtils/testRunner.py b/DeeployTest/testUtils/testRunner.py index 1d274511e2..7d1f7f312a 100644 --- a/DeeployTest/testUtils/testRunner.py +++ b/DeeployTest/testUtils/testRunner.py @@ -10,6 +10,12 @@ import subprocess from typing import Literal, Tuple +import coloredlogs + +from Deeploy.Logging import DEFAULT_FMT +from Deeploy.Logging import DEFAULT_LOGGER as log +from Deeploy.Logging import DETAILED_FILE_LOG_FORMAT, FAILURE_MARK, SUCCESS_MARK + # Source: https://stackoverflow.com/a/38662876 def escapeAnsi(line): @@ -17,18 +23,6 @@ def escapeAnsi(line): return ansi_escape.sub('', line) -def prRed(skk): - print("\033[91m{}\033[00m".format(skk)) - - -def prGreen(skk): - print("\033[92m{}\033[00m".format(skk)) - - -def prBlue(skk): - print("\033[94m{}\033[00m".format(skk)) - - def getPaths(path_test: str, gendir_name: str) -> Tuple[str, str]: dir_test = os.path.normpath(path_test) @@ -100,6 +94,16 @@ def __init__(self, description = None): def parse_args(self, args = None, namespace = None) -> argparse.Namespace: self.args = super().parse_args(args, namespace) + + # Install logger based on verbosity level + if self.args.verbose > 2: + coloredlogs.install(level = 'DEBUG', logger = log, fmt = DETAILED_FILE_LOG_FORMAT) + elif self.args.verbose > 1: + coloredlogs.install(level = 'DEBUG', logger = log, fmt = DEFAULT_FMT) + elif self.args.verbose > 0: + coloredlogs.install(level = 'INFO', logger = log, fmt = DEFAULT_FMT) + else: + coloredlogs.install(level = 'WARNING', logger = log, fmt = DEFAULT_FMT) return self.args @@ -217,7 +221,7 @@ def __init__(self, tiling_arguments: bool, description = None): """) self.add_argument( '--plotMemAlloc', - action = 'store_false', + action = 'store_true', help = 'Turn on plotting of the memory allocation and save it in the deeployState folder\n') self.args = None @@ -232,7 +236,7 @@ def generate_cmd_args(self) -> str: command = "" if self.args.verbose: - command += " -v" + command += " -" + "v" * self.args.verbose if self.args.debug: command += " --debug" if hasattr(self.args, 'profileUntiled') and self.args.profileUntiled: @@ -308,7 +312,7 @@ def __init__(self, if "CMAKE" not in os.environ: if self._args.verbose >= 1: - prRed(f"[TestRunner] CMAKE environment variable not set. Falling back to cmake") + log.error(f"[TestRunner] CMAKE environment variable not set. Falling back to cmake") assert shutil.which( "cmake" ) is not None, "CMake not found. Please check that CMake is installed and available in your system’s PATH, or set the CMAKE environment variable to the full path of your preferred CMake executable." @@ -319,7 +323,7 @@ def __init__(self, print("Test Name : ", self._name_test) def run(self,): - prRed(f"################## Testing {self._dir_test} on {self._platform} Platform ##################") + log.info(f"################## Testing {self._dir_test} on {self._platform} Platform ##################") if self._args.skipgen is False: self.generate_test() @@ -340,8 +344,7 @@ def generate_test(self): command = f"python {generation_script} -d {self._dir_gen} -t {self._dir_test} -p {self._platform} {self.gen_args}" command += self._argument_parser.generate_cmd_args() - if self._args.verbose >= 2: - prBlue(f"[TestRunner] Generation Command: {command}") + log.debug(f"[TestRunner] Generation Command: {command}") err = os.system(command) if err != 0: @@ -364,8 +367,8 @@ def configure_cmake_project(self): if self._args.verbose >= 3: command = "VERBOSE=1 " + command - if self._args.verbose >= 2: - prBlue(f"[TestRunner] Cmake Command: {command}") + + log.debug(f"[TestRunner] Cmake Command: {command}") err = os.system(command) if err != 0: @@ -376,8 +379,8 @@ def build_binary(self): if self._args.verbose >= 3: command = "VERBOSE=1 " + command - if self._args.verbose >= 2: - prBlue(f"[TestRunner] Building Command: {command}") + + log.debug(f"[TestRunner] Building Command: {command}") err = os.system(command) if err != 0: @@ -403,8 +406,7 @@ def run_simulation(self, out_file = 'out.txt'): if self._args.verbose >= 3: command = "BANSHEE_LOG=debug " + command - if self._args.verbose >= 2: - prBlue(f"[TestRunner] Simulation Command: {command}") + log.debug(f"[TestRunner] Simulation Command: {command}") process = subprocess.Popen([command], stdout = subprocess.PIPE, @@ -430,7 +432,7 @@ def run_simulation(self, out_file = 'out.txt'): fileHandle.close() if "Errors: 0 out of " not in result: - prRed(f"⌠Found errors in {self._dir_test}") + log.error(f"{FAILURE_MARK} Found errors in {self._dir_test}") raise RuntimeError(f"Found an error in {self._dir_test}") else: - prGreen(f"✅ No errors found in in {self._dir_test}") + log.info(f"{SUCCESS_MARK} No errors found in in {self._dir_test}") diff --git a/pyproject.toml b/pyproject.toml index 4bd7cb3e70..d807bddab4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ dependencies = [ 'pytest', 'ortools', 'plotly', +'coloredlogs' ] [project.urls] From 15c4a233454859abfc0f43b3defc241b5bf73ce9 Mon Sep 17 00:00:00 2001 From: Matteo Fasulo <74818541+MatteoFasulo@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:54:58 +0200 Subject: [PATCH 11/28] Fix UnsqueezeParser for ONNX Opset 13+ (#119) This PR updates the `Squeeze` and `Unsqueeze` operators to align with the ONNX Opset 13+ standard, where axes is now provided as an input instead of a node attribute. The change is backward compatible, as the old logic remains for single-input cases. A new test case, `CCT/CCT_2_32_32_128_Opset20`, has been added using models exported from PyTorch with ONNX Opset 20 to verify compatibility with recent versions. ## Added - Added support for ONNX Opset 13 and higher. ## Changed - UnsqueezeParser in Generic NodeParser - Check for the presence of `axes` in node attributes and use the old workflow otherwise check for exactly 2 inputs (data and axes). - Node context was changes accordingly; 1 single input follows the old workflow, 2 inputs uses the new 2 input Op. format. ## Fixed - Breaking compilation with ONNX Opset 13 and higher when using `Squeeze` Op. --- .github/workflows/ci-platform-generic.yml | 1 + .github/workflows/ci-platform-siracusa.yml | 1 + CHANGELOG.md | 2 + Deeploy/Targets/Generic/Parsers.py | 40 ++++++++++++++---- .../CCT/CCT_2_32_32_128_Opset20/inputs.npz | Bin 0 -> 12552 bytes .../CCT/CCT_2_32_32_128_Opset20/network.onnx | Bin 0 -> 889835 bytes .../CCT/CCT_2_32_32_128_Opset20/outputs.npz | Bin 0 -> 306 bytes 7 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz create mode 100644 DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/network.onnx create mode 100644 DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml index 6d690befc1..3df422a742 100644 --- a/.github/workflows/ci-platform-generic.yml +++ b/.github/workflows/ci-platform-generic.yml @@ -94,4 +94,5 @@ jobs: miniMobileNet miniMobileNetv2 CCT/CCT_1_16_16_8 + CCT/CCT_2_32_32_128_Opset20 testFloatDemoTinyViT diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml index bee1263539..7c6a5f7541 100644 --- a/.github/workflows/ci-platform-siracusa.yml +++ b/.github/workflows/ci-platform-siracusa.yml @@ -85,5 +85,6 @@ jobs: MLPerf/ImageClassification MLPerf/AnomalyDetection CCT/CCT_1_16_16_8 + CCT/CCT_2_32_32_128_Opset20 testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8 num-cores: 8 diff --git a/CHANGELOG.md b/CHANGELOG.md index b3d601536a..5421cdf526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) +- Fix `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) [#119](https://github.com/pulp-platform/Deeploy/pull/119) ### Added - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough @@ -81,6 +82,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Fixed multiple typos in variable and method names, such as changing `includeGobalReferences` to `includeGlobalReferences` and `dicardedMappers` to `discardedMappers` - Corrected method usage in `importDeeployState` to call `NetworkContext.importNetworkContext` instead of the incorrect method name - Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` +- Fixed `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index 39372c5144..3c3a3472c0 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -940,10 +940,19 @@ def __init__(self): def parseNode(self, node: gs.Node) -> (bool): - ret = all(['axes' in node.attrs, len(node.inputs) == 1, len(node.outputs) == 1]) + # ONNX v11: 'axes' is a node attribute + if 'axes' in node.attrs: + ret = all(['axes' in node.attrs, len(node.inputs) == 1, len(node.outputs) == 1]) + # ONNX v13+: 'axes' becomes an input with the data + # Source: https://onnx.ai/onnx/operators/onnx__Unsqueeze.html + else: + ret = all([len(node.inputs) == 2, len(node.outputs) == 1]) - if ret: - self.operatorRepresentation['axes'] = node.attrs['axes'] + if ret and 'axes' in node.attrs: + axes_attr = node.attrs['axes'] + self.operatorRepresentation['axes'] = [int(axes_attr)] if isinstance(axes_attr, int) \ + else [int(a) for a in axes_attr] + # For opset 13+, axes will be extracted from the second input in parseNodeCtxt return ret @@ -952,13 +961,26 @@ def parseNodeCtxt(self, node: gs.Node, channels_first: bool = True) -> Tuple[NetworkContext, bool]: - inputs = ['data_in'] outputs = ['data_out'] - - for idx, inputNode in enumerate(node.inputs): - self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name - for idx, outputNode in enumerate(node.outputs): - self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name + if len(node.inputs) == 1: + inputs = ['data_in'] + for idx, inputNode in enumerate(node.inputs): + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name + for idx, outputNode in enumerate(node.outputs): + self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name + else: + data_in = ctxt.lookup(node.inputs[0].name) + data_out = ctxt.lookup(node.outputs[0].name) + self.operatorRepresentation['data_in'] = data_in.name + self.operatorRepresentation['data_out'] = data_out.name + # axes must be a constant; extract values + axes_buf = ctxt.lookup(node.inputs[1].name) + assert hasattr(axes_buf, 'values'), "Unsqueeze: expected constant 'axes' input for opset 13+" + axes_vals = np.array(axes_buf.values).astype(int).flatten().tolist() + self.operatorRepresentation['axes'] = axes_vals + # Do not deploy the axes tensor + axes_buf._live = False + axes_buf._deploy = False return ctxt, True diff --git a/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..de35d4d758cd3c025feab8a9e8b80204f7105a3a GIT binary patch literal 12552 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 &ISxYf_yB^e+^4|d`V|dtU%NmWp!^+54STyxG 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

ozJhAuH| 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

kLK+1PYi1ih!l;0td(MlWJN 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�J|)Ae=dgN`y14QKg==nip(zB|6JOKN>`M>* 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 z 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 z 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%0D(a~)i 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 TsP|r7k4@ERKiS9Bw&ni-$_&d{ literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..9686a6345d929bb9bb35e8585823915e42a08982 GIT binary patch literal 306 zcmWIWW@gc4fB;2?XOddZ|Dk}3L4+Z{w4|W4L@%$Pl954xVFgqjjGpWl>KhQr$WX>m zt)7xvoLr=CrJ!z;W}>d6pq`drR8o|f7oT60k_r-cOUx-w1&SAEBo?Fs`5J~g3Wf%n zItsN4 Date: Fri, 24 Oct 2025 15:26:01 +0200 Subject: [PATCH 12/28] Support for 1D Autoencoder (#98) This PR adds required kernels, binding, and templates to support 1D autoencoders. ## Added - Added support for 1D Autoencoder operations, including newly implemented BatchNorm, 1D ConvTranspose, and 1D MaxPool layers. - Added `Autoencoder1D` test to the CI. --- .github/workflows/ci-platform-generic.yml | 1 + CHANGELOG.md | 10 + Deeploy/Targets/Generic/Bindings.py | 73 ++++-- Deeploy/Targets/Generic/Layers.py | 61 +++++ Deeploy/Targets/Generic/Parsers.py | 237 +++++++++++++++++- Deeploy/Targets/Generic/Platform.py | 43 ++-- .../Templates/BatchNormalizationTemplate.py | 15 ++ .../Templates/ConvTransposeTemplate.py | 31 +++ .../Generic/Templates/FloatConvTemplate.py | 26 ++ .../Generic/Templates/FloatMaxPoolTemplate.py | 21 ++ .../Generic/Templates/FloatPadTemplate.py | 39 +++ Deeploy/Targets/Generic/TypeCheckers.py | 14 ++ Deeploy/Targets/MemPool/Platform.py | 4 +- DeeployTest/Tests/Autoencoder1D/inputs.npz | Bin 0 -> 344974 bytes DeeployTest/Tests/Autoencoder1D/network.onnx | Bin 0 -> 344668 bytes DeeployTest/Tests/Autoencoder1D/outputs.npz | Bin 0 -> 1290 bytes .../Generic/inc/DeeployBasicMath.h | 5 + .../Generic/inc/kernel/BatchNorm.h | 16 ++ .../Generic/inc/kernel/ConvTranspose1d_fp32.h | 16 ++ .../Generic/inc/kernel/Convolution.h | 9 + .../Generic/inc/kernel/MaxPool1d.h | 14 ++ TargetLibraries/Generic/src/BatchNorm_fp32.c | 28 +++ .../Generic/src/ConvTranspose1d_fp32.c | 50 ++++ .../Generic/src/Convolution_fp32.c | 29 +++ TargetLibraries/Generic/src/MaxPool1D_fp32.c | 27 ++ 25 files changed, 733 insertions(+), 36 deletions(-) create mode 100644 Deeploy/Targets/Generic/Templates/BatchNormalizationTemplate.py create mode 100644 Deeploy/Targets/Generic/Templates/ConvTransposeTemplate.py create mode 100644 DeeployTest/Tests/Autoencoder1D/inputs.npz create mode 100644 DeeployTest/Tests/Autoencoder1D/network.onnx create mode 100644 DeeployTest/Tests/Autoencoder1D/outputs.npz create mode 100644 TargetLibraries/Generic/inc/kernel/BatchNorm.h create mode 100644 TargetLibraries/Generic/inc/kernel/ConvTranspose1d_fp32.h create mode 100644 TargetLibraries/Generic/inc/kernel/MaxPool1d.h create mode 100644 TargetLibraries/Generic/src/BatchNorm_fp32.c create mode 100644 TargetLibraries/Generic/src/ConvTranspose1d_fp32.c create mode 100644 TargetLibraries/Generic/src/MaxPool1D_fp32.c diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml index 3df422a742..321bed6998 100644 --- a/.github/workflows/ci-platform-generic.yml +++ b/.github/workflows/ci-platform-generic.yml @@ -96,3 +96,4 @@ jobs: CCT/CCT_1_16_16_8 CCT/CCT_2_32_32_128_Opset20 testFloatDemoTinyViT + Autoencoder1D diff --git a/CHANGELOG.md b/CHANGELOG.md index 5421cdf526..158138ccf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Support for 1D Autoencoder [#98](https://github.com/pulp-platform/Deeploy/pull/98) - Refactor Logging for Improved Debugging [#115](https://github.com/pulp-platform/Deeploy/pull/115) - Add reuse-tool as an SPDX license header linter [#113](https://github.com/pulp-platform/Deeploy/pull/113) - Bug fixes, API Cleanup and Reduce Compiler Warning on PULP [#112](https://github.com/pulp-platform/Deeploy/pull/112) @@ -158,6 +159,13 @@ This release containing major architectural changes, new platform support, enhan ### Added +- BatchNorm kernel +- ConvTranspose kernel +- MaxPool1D kernel +- Template for 1D Convolution +- Support for float32 data type in the previous kernels +- Float binding for Pad1D kernel +- Test for Autoencoder1D in the CI pipeline - ChimeraDeployer, currently mainly a placeholder - Allocate templates for Chimera - ChimeraPlatform, using appropriate allocation templates and using the generic Parser + Binding for the Add node @@ -291,6 +299,8 @@ This release containing major architectural changes, new platform support, enhan - `dev-requirements.txt` tracking the dependencies of the build system, linting, documentation, and QOL. ### Changed +- FloatConvTemplate file +- Platform.py file - Bump the CMake version to 3.24 as required for the chimera-sdk - Bump GVSoC's version and add chimera simulation target - Rename the generic source util to utils to avoid name collision with chimera-sdk diff --git a/Deeploy/Targets/Generic/Bindings.py b/Deeploy/Targets/Generic/Bindings.py index 24fc8c0d21..6bfe805b39 100644 --- a/Deeploy/Targets/Generic/Bindings.py +++ b/Deeploy/Targets/Generic/Bindings.py @@ -11,19 +11,20 @@ int8_t, int32_t, uint8_t from Deeploy.DeeployTypes import CodeTransformation, NodeBinding from Deeploy.FutureExtension.CodeTransformationPasses.FutureCodeTransformation import FutureGeneration -from Deeploy.Targets.Generic.Templates import AddTemplate, ConcatTemplate, ConvTemplate, DebugPrintTemplate, \ - DequantTemplate, DummyTemplate, DWConvTemplate, FloatAddTemplate, FloatConvTemplate, FloatDivTemplate, \ - FloatDWConvTemplate, FloatGELUTemplate, FloatGemmTemplate, FloatLayernormTemplate, FloatMatMulTemplate, \ - FloatMaxPoolTemplate, FloatMulTemplate, FloatPadTemplate, FloatReduceMeanTemplate, FloatReluTemplate, \ - FloatSoftmaxTemplate, GatherTemplate, GemmTemplate, IntegerDivTemplate, ITAMaxTemplate, ITAPartialMaxTemplate, \ - MatMulTemplate, MaxPoolTemplate, MulTemplate, PadTemplate, QuantTemplate, ReduceMeanTemplate, ReduceSumTemplate, \ - RequantShiftTemplate, ReshapeTemplate, RQIntegerDivTemplate, RQSiGELUTemplate, SliceTemplate, TransposeTemplate, \ - iGELUTemplate, iLayernormTemplate, iRMSNormTemplate, iSoftmaxTemplate -from Deeploy.Targets.Generic.TypeCheckers import AddChecker, ConcatChecker, ConvChecker, DebugPrintChecker, \ - DequantChecker, DivChecker, DummyChecker, GatherChecker, GELUChecker, GEMMChecker, LayerNormChecker, \ - MatMulChecker, MaxPoolChecker, MulChecker, PadChecker, QuantChecker, ReduceMeanChecker, ReduceSumChecker, \ - ReluChecker, RequantShiftChecker, ReshapeChecker, RQIntegerDivChecker, SliceChecker, SoftmaxChecker, \ - TransposeChecker +from Deeploy.Targets.Generic.Templates import AddTemplate, BatchNormalizationTemplate, ConcatTemplate, ConvTemplate, \ + ConvTransposeTemplate, DebugPrintTemplate, DequantTemplate, DummyTemplate, DWConvTemplate, FloatAddTemplate, \ + FloatConvTemplate, FloatDivTemplate, FloatDWConvTemplate, FloatGELUTemplate, FloatGemmTemplate, \ + FloatLayernormTemplate, FloatMatMulTemplate, FloatMaxPoolTemplate, FloatMulTemplate, FloatPadTemplate, \ + FloatReduceMeanTemplate, FloatReluTemplate, FloatSoftmaxTemplate, GatherTemplate, GemmTemplate, \ + IntegerDivTemplate, ITAMaxTemplate, ITAPartialMaxTemplate, MatMulTemplate, MaxPoolTemplate, MulTemplate, \ + PadTemplate, QuantTemplate, ReduceMeanTemplate, ReduceSumTemplate, RequantShiftTemplate, ReshapeTemplate, \ + RQIntegerDivTemplate, RQSiGELUTemplate, SliceTemplate, TransposeTemplate, iGELUTemplate, iLayernormTemplate, \ + iRMSNormTemplate, iSoftmaxTemplate +from Deeploy.Targets.Generic.TypeCheckers import AddChecker, BatchNormChecker, ConcatChecker, ConvChecker, \ + DebugPrintChecker, DequantChecker, DivChecker, DummyChecker, GatherChecker, GELUChecker, GEMMChecker, \ + LayerNormChecker, MatMulChecker, MaxPoolChecker, MulChecker, PadChecker, QuantChecker, ReduceMeanChecker, \ + ReduceSumChecker, ReluChecker, RequantShiftChecker, ReshapeChecker, RQIntegerDivChecker, SliceChecker, \ + SoftmaxChecker, TransposeChecker BasicTransformer = CodeTransformation([ArgumentStructGeneration(), MemoryManagementGeneration(), FutureGeneration()]) @@ -53,8 +54,14 @@ FloatAddTemplate.referenceTemplate, BasicTransformer) ] -BasicConv1DBinding = NodeBinding(ConvChecker([PointerClass(int8_t), PointerClass(int8_t)], [PointerClass(int32_t)]), - ConvTemplate.reference1DTemplate, BasicTransformer) +BasicConv1DBindings = [ + NodeBinding(ConvChecker( + [PointerClass(type), PointerClass(type), PointerClass(type)], [PointerClass(type)]), + FloatConvTemplate.reference1DTemplate, BasicTransformer) for type in FloatDataTypes +] + [ + NodeBinding(ConvChecker([PointerClass(int8_t), PointerClass(int8_t)], [PointerClass(int32_t)]), + ConvTemplate.reference1DTemplate, BasicTransformer) +] BasicDWConv1DBinding = NodeBinding(ConvChecker([PointerClass(int8_t), PointerClass(int8_t)], [PointerClass(int32_t)]), DWConvTemplate.reference1DTemplate, BasicTransformer) @@ -147,6 +154,11 @@ FloatMatMulTemplate.referenceTemplate, BasicTransformer) ] +BasicMaxPool1DBindings = [ + NodeBinding(MaxPoolChecker([PointerClass(type)], [PointerClass(type)]), FloatMaxPoolTemplate.reference1DTemplate, + BasicTransformer) for type in FloatDataTypes +] + BasicMaxPool2DBindings = [ NodeBinding(MaxPoolChecker([PointerClass(int8_t)], [PointerClass(int8_t)]), MaxPoolTemplate.referenceTemplate, BasicTransformer) @@ -167,7 +179,11 @@ BasicPad1DBindings = [ NodeBinding(PadChecker([PointerClass(type)], [PointerClass(type)]), PadTemplate.reference1DTemplate, BasicTransformer) for type in SignedIntegerDataTypes +] + [ + NodeBinding(PadChecker([PointerClass(type)], [PointerClass(type)]), FloatPadTemplate.reference1DTemplate, + BasicTransformer) for type in FloatDataTypes ] + BasicPad2DBindings = [ NodeBinding(PadChecker([PointerClass(type)], [PointerClass(type)]), PadTemplate.reference2DTemplate, BasicTransformer) for type in SignedIntegerDataTypes @@ -266,3 +282,30 @@ NodeBinding(DequantChecker([PointerClass(int32_t)], [PointerClass(float32_t)]), DequantTemplate.referenceTemplate, BasicTransformer), ] + +BasicBatchNormBindings = [ + NodeBinding( + BatchNormChecker( + [PointerClass(type), + PointerClass(type), + PointerClass(type), + PointerClass(type), + PointerClass(type)], [PointerClass(type)]), BatchNormalizationTemplate.referenceTemplate, BasicTransformer) + for type in FloatDataTypes +] + +BasicConvTransposeBindings = [ + NodeBinding( + ConvChecker( + [PointerClass(type), PointerClass(type), PointerClass(type)], # input, weight, bias + [PointerClass(type)]), + ConvTransposeTemplate.referenceTemplate, + BasicTransformer) for type in FloatDataTypes +] + [ + NodeBinding( + ConvChecker( + [PointerClass(type), PointerClass(type)], # input, weight + [PointerClass(type)]), + ConvTransposeTemplate.referenceTemplate, + BasicTransformer) for type in FloatDataTypes +] diff --git a/Deeploy/Targets/Generic/Layers.py b/Deeploy/Targets/Generic/Layers.py index e01f5e79d0..c924895c13 100644 --- a/Deeploy/Targets/Generic/Layers.py +++ b/Deeploy/Targets/Generic/Layers.py @@ -618,3 +618,64 @@ class DequantLayer(ONNXLayer): def __init__(self, maps: List[NodeMapper]): super().__init__(maps) + + +class BatchNormalizationLayer(ONNXLayer): + + def __init__(self, maps: List[NodeMapper]): + super().__init__(maps) + + def computeOps(self): + # 5 operations per element: sub, mul, add, sqrt, div + B = self.mapper.parser.operatorRepresentation['batch_size'] + C = self.mapper.parser.operatorRepresentation['channel_size'] + W = self.mapper.parser.operatorRepresentation['window_size'] + return B * C * W * 5 + + +class ConvTransposeLayer(ONNXLayer): + + def __init__(self, maps: List[NodeMapper]): + super().__init__(maps) + + def computeShapes(self, inputShapes: Shape, outputShapes: Shape, operatorRepresentation, + channels_first) -> Tuple[Shape, Shape]: + """ + Infers output shapes for ConvTranspose using only static info. + - inputShapes[0]: input tensor shape (e.g., [N, C_in, W] for 1D, [N, C_in, H, W] for 2D) + - inputShapes[1]: weight tensor shape (e.g., [C_in, C_out // group, kW] for 1D) + - outputShapes[0]: output tensor shape (to be updated) + """ + newInputShapes = list(inputShapes) + newOutputShapes = list(outputShapes) + group = operatorRepresentation.get('group', 1) + weight_shape = inputShapes[1] + + if newOutputShapes and len(newOutputShapes[0]) >= 2: + # For 1D: weight_shape = [C_in, C_out // group, kW] + # For 2D: weight_shape = [C_in, C_out // group, kH, kW] + ch_out = weight_shape[1] * group + if channels_first: + newOutputShapes[0][1] = ch_out + else: + newOutputShapes[0][-1] = ch_out + + return newInputShapes, newOutputShapes + + def computeOps(self): + opRep = self.mapper.parser.operatorRepresentation + + groups = opRep.get('group', 1) + kernel_shape = np.prod(opRep['kernel_shape']) # es. [3, 3] -> 9 + ch_in = opRep['ch_im_in'] + ch_out = opRep['ch_im_out'] + + opsPerPx = int(kernel_shape * ch_in * ch_out / groups) * 2 + + # ConvTranspose upscales spatial dims, quindi num pixel viene da output + if 'dim_im_out_y' in opRep: + numPx = opRep['dim_im_out_x'] * opRep['dim_im_out_y'] + else: + numPx = opRep['dim_im_out_x'] + + return numPx * opsPerPx diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index 3c3a3472c0..adc48ffe15 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -221,6 +221,48 @@ def parseNodeCtxt(self, return ctxt, True +class MaxPool1DParser(MaxPoolParser): + + def __init__(self): + super().__init__() + + def parseNode(self, node: gs.Node) -> bool: + ret = super().parseNode(node) + wellFormed = False + if ret: + pads = self.operatorRepresentation['pads'] + kernel_shape = self.operatorRepresentation['kernel_shape'] + strides = self.operatorRepresentation['strides'] + # 1D: pads should be length 2, kernel_shape length 1, strides length 1 + if len(pads) == 2 and len(kernel_shape) == 1 and len(strides) == 1: + wellFormed = True + self.operatorRepresentation['padding_y'] = int(pads[0]) + self.operatorRepresentation['padding_y_right'] = int(pads[1]) + self.operatorRepresentation['stride_y'] = int(strides[0]) + self.operatorRepresentation['dim_kernel_y'] = int(kernel_shape[0]) + return wellFormed + + def parseNodeCtxt(self, ctxt, node, channels_first = True): + newCtxt, ret = super().parseNodeCtxt(ctxt, node, channels_first) + if ret: + data_in = newCtxt.lookup(self.operatorRepresentation['data_in']) + data_out = newCtxt.lookup(self.operatorRepresentation['data_out']) + self.operatorRepresentation['batch'] = data_in.shape[0] + if channels_first: + self.operatorRepresentation['ch_im_in'] = data_in.shape[1] + self.operatorRepresentation['dim_im_in_y'] = data_in.shape[2] + self.operatorRepresentation['ch_im_out'] = data_out.shape[1] + self.operatorRepresentation['dim_im_out_y'] = data_out.shape[2] + else: + self.operatorRepresentation['ch_im_in'] = data_in.shape[2] + self.operatorRepresentation['dim_im_in_y'] = data_in.shape[1] + self.operatorRepresentation['ch_im_out'] = data_out.shape[2] + self.operatorRepresentation['dim_im_out_y'] = data_out.shape[1] + if len(data_in.shape) == 3 and len(data_out.shape) == 3: + return newCtxt, True + return ctxt, False + + class MaxPool2DParser(MaxPoolParser): def __init__(self): @@ -298,7 +340,12 @@ def parseNode(self, node: gs.Node) -> bool: if ret: self.operatorRepresentation['mode'] = node.attrs['mode'] - self.operatorRepresentation['pads'] = node.attrs['pads'] + + try: + self.operatorRepresentation['pads'] = [int(p) for p in node.attrs['pads']] + except Exception as e: + self.operatorRepresentation['pads'] = node.attrs['pads'] + self.operatorRepresentation['value'] = node.attrs['value'] return ret @@ -1325,6 +1372,8 @@ def parseNodeCtxt(self, self.operatorRepresentation['batch'] = data_in.shape[0] self.operatorRepresentation['dim_im_in_x'] = 1 + + # Necessary, since we use the same Convlayer for all convolutions self.operatorRepresentation['dim_im_out_x'] = 1 if channels_first: @@ -1338,6 +1387,11 @@ def parseNodeCtxt(self, self.operatorRepresentation['ch_im_out'] = data_out.shape[2] self.operatorRepresentation['dim_im_out_y'] = data_out.shape[1] + self.operatorRepresentation[ + 'batchOffsetIn'] = self.operatorRepresentation['ch_im_in'] * self.operatorRepresentation['dim_im_in_y'] + self.operatorRepresentation['batchOffsetOut'] = self.operatorRepresentation[ + 'ch_im_out'] * self.operatorRepresentation['dim_im_out_y'] + if len(data_in.shape) == 3 and len(weight.shape) == 3: return newCtxt, True @@ -2136,7 +2190,20 @@ def parseNodeCtxt(self, if ret: inputs = ['data_in', 'weight'] + + # Handle bias, if present + if len(node.inputs) > 2: + inputs.append("bias") + self.operatorRepresentation["has_bias"] = 1 + else: + self.operatorRepresentation["has_bias"] = 0 + self.operatorRepresentation["bias"] = "NULL" + for idx, inputNode in enumerate(node.inputs): + if idx >= len(inputs): + raise IndexError( + f"Index {idx} out of range for inputs of length {len(inputs)} in node {inputNode.name}") + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name return newCtxt, True @@ -2555,3 +2622,171 @@ def parseNodeCtxt(self, self.operatorRepresentation['lr'] = node.attrs['lr'] return ctxt, True + + +class BatchNormParser(NodeParser): + + def __init__(self): + super().__init__() + + def parseNode(self, node: gs.Node) -> bool: + # Verify the attributes (epsilon is mandatory, momentum and training_mode are optional) + if 'epsilon' not in node.attrs: + return False + # Common Inputs: 5 (X, scale, B, mean, var) + if len(node.inputs) < 5: + return False + + # Save the attributes, default values are provided if not present + self.operatorRepresentation['epsilon'] = node.attrs.get('epsilon', 1e-5) + self.operatorRepresentation['momentum'] = node.attrs.get('momentum', 0.9) + self.operatorRepresentation['training_mode'] = node.attrs.get('training_mode', 0) + + return True + + def parseNodeCtxt(self, ctxt, node: gs.Node, channels_first: bool = True): + inputs = ['data_in', 'scale', 'bias', 'mean', 'variance'] + outputs = ['data_out'] + + for idx, inputNode in enumerate(node.inputs[:5]): + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name + + # Output (Y) + self.operatorRepresentation[outputs[0]] = ctxt.lookup(node.outputs[0].name).name + + input_shape = ctxt.lookup(node.inputs[0].name).shape + # Save input shape information + self.operatorRepresentation['batch_size'] = input_shape[0] + self.operatorRepresentation['channel_size'] = input_shape[1] + self.operatorRepresentation['window_size'] = input_shape[2] + + return ctxt, True + + +class ConvTransposeParser(NodeParser): + + def __init__(self): + super().__init__() + + def parseNode(self, node: gs.Node) -> bool: + # Extract ONNX attributes with defaults + strides = node.attrs.get('strides', [1]) + + pads = node.attrs.get('pads', [0, 0]) + kernel_shape = node.attrs.get('kernel_shape', None) + dilations = node.attrs.get('dilations', [1]) + group = node.attrs.get('group', 1) + + # Check for required attributes + wellFormed = (kernel_shape is not None and len(node.outputs) == 1) + if wellFormed: + self.operatorRepresentation['strides'] = strides + self.operatorRepresentation['pads'] = pads + self.operatorRepresentation['kernel_shape'] = kernel_shape + self.operatorRepresentation['dilations'] = dilations + self.operatorRepresentation['group'] = group + self.operatorRepresentation['nodeName'] = node.name + self.operatorRepresentation['nodeOp'] = node.op + return wellFormed + + def parseNodeCtxt(self, ctxt: NetworkContext, node: gs.Node, channels_first: bool = True): + # Register buffer names for codegen + self.operatorRepresentation['data_in'] = node.inputs[0].name + self.operatorRepresentation['weight'] = node.inputs[1].name + self.operatorRepresentation['data_out'] = node.outputs[0].name + if len(node.inputs) == 3: + self.operatorRepresentation['bias'] = node.inputs[2].name + self.operatorRepresentation['has_bias'] = "true" + else: + self.operatorRepresentation['has_bias'] = "false" + # Get output shape from context + data_out = ctxt.lookup(node.outputs[0].name) + out_shape = data_out.shape + if len(out_shape) == 3: + self.operatorRepresentation['dim_im_out_x'] = out_shape[2] + elif len(out_shape) == 4: + self.operatorRepresentation['dim_im_out_x'] = out_shape[2] + self.operatorRepresentation['dim_im_out_y'] = out_shape[3] + + stride_x, stride_y = 1, 1 + if "strides" in node.attrs: + stride_y = node.attrs["strides"][0] + stride_x = node.attrs["strides"][1] if len(node.attrs["strides"]) > 1 else stride_y + self.operatorRepresentation["stride_y"] = stride_y + self.operatorRepresentation["stride_x"] = stride_x + + if "kernel_shape" in node.attrs: + kernel_shape = node.attrs["kernel_shape"] + kernel_shape_x = kernel_shape[0] + # For 2D, kernel_shape may have two elements + kernel_shape_y = kernel_shape[1] if len(kernel_shape) > 1 else kernel_shape_x + else: + kernel_shape_x = 1 + kernel_shape_y = 1 + + data_in = ctxt.lookup(node.inputs[0].name) + data_out = ctxt.lookup(node.outputs[0].name) + in_shape = data_in.shape + out_shape = data_out.shape + + self.operatorRepresentation['ch_im_in'] = in_shape[1] + self.operatorRepresentation['dim_im_in_y'] = in_shape[2] + self.operatorRepresentation['ch_im_out'] = out_shape[1] + self.operatorRepresentation['dim_im_out_y'] = out_shape[2] + + self.operatorRepresentation[ + 'batchOffsetIn'] = self.operatorRepresentation['ch_im_in'] * self.operatorRepresentation['dim_im_in_y'] + self.operatorRepresentation[ + 'batchOffsetOut'] = self.operatorRepresentation['ch_im_out'] * self.operatorRepresentation['dim_im_out_y'] + return ctxt, True + + +class ConvTranspose1DParser(ConvTransposeParser): + + def __init__(self): + super().__init__() + + def parseNode(self, node: gs.Node) -> bool: + # 1D ConvTranspose expects 3D input/output and 3D weight + wellFormed = super().parseNode(node) + ret = False + if wellFormed: + ret = all([ + # Make sure strides are 2D + len(node.attrs['strides']) == 1, + len(node.attrs['pads']) == 2, + len(node.attrs['dilations']) == 1, + ]) + if ret: + + self.operatorRepresentation['kernel_shape'] = node.attrs['kernel_shape'] + self.operatorRepresentation['dim_kernel_y'] = int(self.operatorRepresentation['kernel_shape'][0]) + self.operatorRepresentation['dilation_y'] = int(self.operatorRepresentation['dilations'][0]) + self.operatorRepresentation['padding_y'] = int(self.operatorRepresentation['pads'][0]) + self.operatorRepresentation['stride_y'] = int(self.operatorRepresentation['strides'][0]) + + return ret + + def parseNodeCtxt(self, + ctxt: NetworkContext, + node: gs.Node, + channels_first: bool = True) -> Tuple[NetworkContext, bool]: + + newCtxt, ret = super().parseNodeCtxt(ctxt, node, channels_first) + + if ret: + data_in = newCtxt.lookup(node.inputs[0].name) + data_out = newCtxt.lookup(node.outputs[0].name) + in_shape = data_in.shape + out_shape = data_out.shape + self.operatorRepresentation['batch'] = in_shape[0] + self.operatorRepresentation['ch_im_in'] = in_shape[1] + self.operatorRepresentation['dim_im_in_y'] = in_shape[2] + self.operatorRepresentation['ch_im_out'] = out_shape[1] + self.operatorRepresentation['dim_im_out_y'] = out_shape[2] + self.operatorRepresentation[ + "batchOffsetIn"] = self.operatorRepresentation["ch_im_in"] * self.operatorRepresentation["dim_im_in_y"] + self.operatorRepresentation["batchOffsetOut"] = self.operatorRepresentation[ + "ch_im_out"] * self.operatorRepresentation["dim_im_out_y"] + return newCtxt, True + return ctxt, False diff --git a/Deeploy/Targets/Generic/Platform.py b/Deeploy/Targets/Generic/Platform.py index c09b89df96..a15b3db2e6 100644 --- a/Deeploy/Targets/Generic/Platform.py +++ b/Deeploy/Targets/Generic/Platform.py @@ -6,30 +6,33 @@ RemoveEmptyConvBiasPass from Deeploy.DeeployTypes import ConstantBuffer, DeploymentEngine, DeploymentPlatform, NodeMapper, NodeTemplate, \ StructBuffer, TopologyOptimizer, TransientBuffer, VariableBuffer -from Deeploy.Targets.Generic.Bindings import BasicAddBindings, BasicConcatBindings, BasicConv1DBinding, \ - BasicConv2DBindings, BasicDebugPrintBindings, BasicDequantBindings, BasicDivBindings, BasicDWConv1DBinding, \ - BasicDWConv2DBindings, BasicGatherBindings, BasicGELUBindings, BasicGEMMBindings, BasicITAPartialSoftmaxBinding, \ - BasicITASoftmaxBinding, BasicLayerNormBindings, BasicMatMulBindings, BasicMaxPool2DBindings, BasicMulBindings, \ +from Deeploy.Targets.Generic.Bindings import BasicAddBindings, BasicBatchNormBindings, BasicConcatBindings, \ + BasicConv1DBindings, BasicConv2DBindings, BasicConvTransposeBindings, BasicDebugPrintBindings, \ + BasicDequantBindings, BasicDivBindings, BasicDWConv1DBinding, BasicDWConv2DBindings, BasicGatherBindings, \ + BasicGELUBindings, BasicGEMMBindings, BasicITAPartialSoftmaxBinding, BasicITASoftmaxBinding, \ + BasicLayerNormBindings, BasicMatMulBindings, BasicMaxPool1DBindings, BasicMaxPool2DBindings, BasicMulBindings, \ BasicPad1DBindings, BasicPad2DBindings, BasicQuantBindings, BasicReduceMeanBindings, BasicReduceSumBindings, \ BasicReluBinding, BasicReshapeBindings, BasicRQIntegerDivBinding, BasicRQSBindings, BasicRQSGELUBinding, \ BasicSliceBindings, BasicSoftmaxBindings, BasicTransposeBindings, DummyBinding -from Deeploy.Targets.Generic.Layers import AddLayer, ConcatLayer, ConvLayer, DebugPrintLayer, DequantLayer, DivLayer, \ - GatherLayer, GELULayer, GEMMLayer, ITAMaxLayer, LayerNormLayer, MatMulLayer, MaxPoolLayer, MulLayer, PadLayer, \ - QuantLayer, ReduceMeanLayer, ReduceSumLayer, ReluLayer, RequantShiftLayer, ReshapeLayer, RQIntegerDivLayer, \ - RQSiGELULayer, SliceLayer, SoftmaxLayer, TransposeLayer -from Deeploy.Targets.Generic.Parsers import AddParser, ConcatParser, DebugParser, DequantParser, DivParser, \ - DummyParser, FlattenParser, GatherParser, GELUParser, GenericConv1DParser, GenericConv2DParser, \ - GenericDWConv1DParser, GenericDWConv2DParser, GenericGEMMParser, GenericMaxPool2DParser, IntegerDivParser, \ - ITAMaxParser, ITAPartialMaxParser, LayerNormParser, MatMulParser, MulParser, Pad1DParser, Pad2DParser, \ - QuantParser, ReduceMeanParser, ReduceSumParser, ReluParser, RequantShiftParser, ReshapeParser, RQIntegerDivParser, \ - RQSiGELUParser, SliceParser, SoftmaxParser, TransposeParser, UnsqueezeParser, iLayerNormParser, iSoftmaxParser +from Deeploy.Targets.Generic.Layers import AddLayer, BatchNormalizationLayer, ConcatLayer, ConvLayer, \ + ConvTransposeLayer, DebugPrintLayer, DequantLayer, DivLayer, GatherLayer, GELULayer, GEMMLayer, ITAMaxLayer, \ + LayerNormLayer, MatMulLayer, MaxPoolLayer, MulLayer, PadLayer, QuantLayer, ReduceMeanLayer, ReduceSumLayer, \ + ReluLayer, RequantShiftLayer, ReshapeLayer, RQIntegerDivLayer, RQSiGELULayer, SliceLayer, SoftmaxLayer, \ + TransposeLayer +from Deeploy.Targets.Generic.Parsers import AddParser, BatchNormParser, ConcatParser, ConvTranspose1DParser, \ + DebugParser, DequantParser, DivParser, DummyParser, FlattenParser, GatherParser, GELUParser, GenericConv1DParser, \ + GenericConv2DParser, GenericDWConv1DParser, GenericDWConv2DParser, GenericGEMMParser, GenericMaxPool2DParser, \ + IntegerDivParser, ITAMaxParser, ITAPartialMaxParser, LayerNormParser, MatMulParser, MaxPool1DParser, MulParser, \ + Pad1DParser, Pad2DParser, QuantParser, ReduceMeanParser, ReduceSumParser, ReluParser, RequantShiftParser, \ + ReshapeParser, RQIntegerDivParser, RQSiGELUParser, SliceParser, SoftmaxParser, TransposeParser, UnsqueezeParser, \ + iLayerNormParser, iSoftmaxParser from Deeploy.Targets.Generic.Templates import AllocateTemplate, FreeTemplate from Deeploy.Targets.Generic.TopologyOptimizationPasses.Passes import DequantPatternPass, ExtractPaddingFromConvPass, \ ExtractPaddingFromPoolPass, MatMulAddMergePass, MergeConstAddAndRequantPass, QuantPatternPass, \ iGELURequantMergePass AddMapper = NodeMapper(AddParser(), BasicAddBindings) -Conv1DMapper = NodeMapper(GenericConv1DParser(), [BasicConv1DBinding]) +Conv1DMapper = NodeMapper(GenericConv1DParser(), BasicConv1DBindings) Conv2DMapper = NodeMapper(GenericConv2DParser(), BasicConv2DBindings) ConcatMapper = NodeMapper(ConcatParser(), BasicConcatBindings) DebugMapper = NodeMapper(DebugParser(), BasicDebugPrintBindings) @@ -47,6 +50,7 @@ ITAPartialMaxMapper = NodeMapper(ITAPartialMaxParser(), [BasicITAPartialSoftmaxBinding]) MatMulMapper = NodeMapper(MatMulParser(), BasicMatMulBindings) MaxPoolMapper = NodeMapper(GenericMaxPool2DParser(), BasicMaxPool2DBindings) +MaxPool1DMapper = NodeMapper(MaxPool1DParser(), BasicMaxPool1DBindings) MulMapper = NodeMapper(MulParser(), BasicMulBindings) Pad1DMapper = NodeMapper(Pad1DParser(), BasicPad1DBindings) Pad2DMapper = NodeMapper(Pad2DParser(), BasicPad2DBindings) @@ -63,7 +67,8 @@ UnsqueezeMapper = NodeMapper(UnsqueezeParser(), BasicReshapeBindings) QuantMapper = NodeMapper(QuantParser(), BasicQuantBindings) DequantMapper = NodeMapper(DequantParser(), BasicDequantBindings) - +BatchNormalizationMapper = NodeMapper(BatchNormParser(), BasicBatchNormBindings) +ConvTransposeMapper = NodeMapper(ConvTranspose1DParser(), BasicConvTransposeBindings) SliceMapper = NodeMapper(SliceParser(), BasicSliceBindings) # Dummy nodes are intended for development purposes only! @@ -91,7 +96,7 @@ 'ITAPartialMax': ITAMaxLayer([ITAPartialMaxMapper]), 'MatMul': GEMMLayer([MatMulMapper]), 'MatMulInteger': MatMulLayer([MatMulMapper]), - 'MaxPool': MaxPoolLayer([MaxPoolMapper]), + 'MaxPool': MaxPoolLayer([MaxPool1DMapper, MaxPoolMapper]), 'Mul': MulLayer([MulMapper]), 'Pad': PadLayer([Pad1DMapper, Pad2DMapper]), 'ReduceMean': ReduceMeanLayer([ReduceMeanMapper]), @@ -106,7 +111,9 @@ 'Unsqueeze': ReshapeLayer([UnsqueezeMapper]), 'Slice': SliceLayer([SliceMapper]), 'Quant': QuantLayer([QuantMapper]), - 'Dequant': DequantLayer([DequantMapper]) + 'Dequant': DequantLayer([DequantMapper]), + 'BatchNormalization': BatchNormalizationLayer([BatchNormalizationMapper]), + 'ConvTranspose': ConvTransposeLayer([ConvTransposeMapper]) # # For example, you can use the DummpyMapper, in case you want to test # # deployment or optimizations with GlobalAveragePool nodes but did not yet # # implement the corresponding kernel diff --git a/Deeploy/Targets/Generic/Templates/BatchNormalizationTemplate.py b/Deeploy/Targets/Generic/Templates/BatchNormalizationTemplate.py new file mode 100644 index 0000000000..5377c91ca0 --- /dev/null +++ b/Deeploy/Targets/Generic/Templates/BatchNormalizationTemplate.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +from Deeploy.DeeployTypes import NodeTemplate + +referenceTemplate = NodeTemplate(""" +// BatchNorm (Name: ${nodeName}, Op: ${nodeOp}) +BEGIN_SINGLE_CORE + BatchNorm_fp32( + ${data_in}, ${scale}, ${bias}, ${mean}, ${variance}, + ${data_out}, ${batch_size}, ${channel_size}, ${window_size} + ); +END_SINGLE_CORE +""") diff --git a/Deeploy/Targets/Generic/Templates/ConvTransposeTemplate.py b/Deeploy/Targets/Generic/Templates/ConvTransposeTemplate.py new file mode 100644 index 0000000000..9bf864c91f --- /dev/null +++ b/Deeploy/Targets/Generic/Templates/ConvTransposeTemplate.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +from Deeploy.DeeployTypes import NodeTemplate + +referenceTemplate = NodeTemplate(""" +<% +batchOffsetIn = ch_im_in * dim_im_in_y +batchOffsetOut = ch_im_out * dim_im_out_y +%> + +// 1D Transposed Conv (Name: ${nodeName}, Op: ${nodeOp}) +BEGIN_SINGLE_CORE + ${data_in_type.typeName} ref_${data_out}_${data_in} = ${data_in}; + ${data_out_type.typeName} ref_${data_out}_${data_out} = ${data_out}; + + for (uint32_t n=0; n<${batch}; ++n) { + ConvTranspose1d_fp32( + ref_${data_out}_${data_in}, ${ch_im_in}, ${dim_im_in_y}, + ${weight}, ${ch_im_out}, ${dim_kernel_y}, + ${stride_y}, + ${bias}, ${has_bias}, + ref_${data_out}_${data_out}, ${dim_im_out_y} + ); + + ref_${data_out}_${data_in} += ${batchOffsetIn}; + ref_${data_out}_${data_out} += ${batchOffsetOut}; + } +END_SINGLE_CORE +""") diff --git a/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py b/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py index f1cb7f15ab..7519d33a21 100644 --- a/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatConvTemplate.py @@ -29,3 +29,29 @@ } END_SINGLE_CORE """) + +reference1DTemplate = NodeTemplate(""" +<% +batchOffsetIn = ch_im_in * dim_im_in_y +batchOffsetOut = ch_im_out * dim_im_out_y +%> + // 1D FP Conv (Name: ${nodeName}, Op: ${nodeOp}) + BEGIN_SINGLE_CORE + ${data_in_type.typeName} ref_${data_out}_${data_in} = ${data_in}; + ${data_out_type.typeName} ref_${data_out}_${data_out} = ${data_out}; + for (uint32_t n=0; n<${batch}; ++n) { + Conv1d_fp${data_in_type.referencedType.typeWidth}_fp${weight_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}( + ref_${data_out}_${data_in}, ${ch_im_in}, ${dim_im_in_y}, + ${weight}, ${ch_im_out}, ${dim_kernel_y}, + ${stride_y}, + ${bias}, + ${has_bias}, + ref_${data_out}_${data_out}, + ${dim_im_out_y} + ); + + ref_${data_out}_${data_in} += ${batchOffsetIn}; + ref_${data_out}_${data_out} += ${batchOffsetOut}; + } + END_SINGLE_CORE + """) \ No newline at end of file diff --git a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py index b5401d174f..1eef5e0f4f 100644 --- a/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatMaxPoolTemplate.py @@ -20,3 +20,24 @@ } END_SINGLE_CORE """) + +reference1DTemplate = NodeTemplate(""" +<% +batchOffsetIn = ch_im_in * dim_im_in_y +batchOffsetOut = ch_im_out * dim_im_out_y +%> + // 1D Float MaxPool (Name: ${nodeName}, Op: ${nodeOp}) + BEGIN_SINGLE_CORE + ${data_in_type.typeName} ref_${data_out}_${data_in} = ${data_in}; + ${data_out_type.typeName} ref_${data_out}_${data_out} = ${data_out}; + for (uint32_t n=0; n<${batch}; ++n) { + MaxPool1d_fp32_fp32( + ref_${data_out}_${data_in}, ${ch_im_in}, ${dim_im_in_y}, + ${dim_kernel_y}, ${stride_y}, + ref_${data_out}_${data_out} + ); + ref_${data_out}_${data_in} += ${batchOffsetIn}; + ref_${data_out}_${data_out} += ${batchOffsetOut}; + } + END_SINGLE_CORE +""") \ No newline at end of file diff --git a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py index c1bd567641..ad528910b7 100644 --- a/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py +++ b/Deeploy/Targets/Generic/Templates/FloatPadTemplate.py @@ -52,3 +52,42 @@ %endif END_SINGLE_CORE """) + +reference1DTemplate = NodeTemplate(""" +<% + x_offset_out = dim_im_out_ch*(pad_y) + width = dim_im_in_ch*dim_im_in_y + + startPosX = x_offset_out + +batchOffsetOut = dim_im_out_ch * dim_im_out_y +%> + +// 1D Float Pad (Name: ${nodeName}, Op: ${nodeOp}) +BEGIN_SINGLE_CORE + for (uint32_t i = 0; i < ${data_out_size}; i++) { + ${data_out}[i] = ${value}; + } + uint32_t xoffset_${data_out}_${data_in}; + uint32_t offset_in_${data_out}_${data_in} = 0; + + % if channels_first: + // NCHW Layout + for(uint32_t n=0; n<${batch}; n++){ + xoffset_${data_out}_${data_in} = n*${batchOffsetOut} +${pad_y}; + for (uint32_t c=0; c<${dim_im_in_ch}; ++c) { + memcpy(${data_out} + xoffset_${data_out}_${data_in}, ${data_in}+offset_in_${data_out}_${data_in}, ${dim_im_in_y}*sizeof(${data_out_type.referencedType.typeName})); + xoffset_${data_out}_${data_in} += ${dim_im_out_y}; + offset_in_${data_out}_${data_in} += ${dim_im_in_y}; + } + } + % else: + // NHWC Layout + for(uint32_t n=0; n<${batch}; n++){ + xoffset_${data_out}_${data_in} = n*${batchOffsetOut} + ${startPosX}; + memcpy(${data_out}+xoffset_${data_out}_${data_in}, ${data_in}+offset_in_${data_out}_${data_in}, ${width}*sizeof(${data_out_type.referencedType.typeName})); + offset_in_${data_out}_${data_in} += ${width}; + } + %endif +END_SINGLE_CORE +""") diff --git a/Deeploy/Targets/Generic/TypeCheckers.py b/Deeploy/Targets/Generic/TypeCheckers.py index 8f3a12ec8d..c2c8d436f8 100644 --- a/Deeploy/Targets/Generic/TypeCheckers.py +++ b/Deeploy/Targets/Generic/TypeCheckers.py @@ -596,3 +596,17 @@ def _inferNumLevels(self, inputs: List[VariableBuffer], def _inferSignedness(self, inputs: List[VariableBuffer], operatorRepresentation: OperatorRepresentation) -> Optional[List[bool]]: return [True] + + +class BatchNormChecker(SignPropTypeChecker): + + def __init__(self, input_types: Sequence[Type[Pointer]], output_types: Sequence[Type[Pointer]]): + super().__init__(input_types, output_types) + + def _inferNumLevels(self, inputs: List[VariableBuffer], + operatorRepresentation: OperatorRepresentation) -> List[int]: + return [2**(self.input_types[0].referencedType.typeWidth)] + + def _inferSignedness(self, inputs: List[VariableBuffer], + operatorRepresentation: OperatorRepresentation) -> List[bool]: + return [True] diff --git a/Deeploy/Targets/MemPool/Platform.py b/Deeploy/Targets/MemPool/Platform.py index 4f1a982988..48599736f4 100644 --- a/Deeploy/Targets/MemPool/Platform.py +++ b/Deeploy/Targets/MemPool/Platform.py @@ -8,7 +8,7 @@ from Deeploy.DeeployTypes import ConstantBuffer, DeploymentEngine, DeploymentPlatform, NodeMapper, NodeTemplate, \ StructBuffer, TopologyOptimizer, TransientBuffer, VariableBuffer -from Deeploy.Targets.Generic.Bindings import BasicAddBindings, BasicConv1DBinding, BasicConv2DBindings, \ +from Deeploy.Targets.Generic.Bindings import BasicAddBindings, BasicConv1DBindings, BasicConv2DBindings, \ BasicDebugPrintBindings, BasicDivBindings, BasicDWConv1DBinding, BasicDWConv2DBindings, BasicGatherBindings, \ BasicGELUBindings, BasicLayerNormBindings, BasicMulBindings, BasicPad1DBindings, BasicPad2DBindings, \ BasicReduceMeanBindings, BasicReduceSumBindings, BasicReshapeBindings, BasicRQIntegerDivBinding, \ @@ -37,7 +37,7 @@ # Fallback bindings from the generic platform # (they support a wider range of attribute values) -GenericConv1D_Mapper = NodeMapper(GenericConv1DParser(), [BasicConv1DBinding]) +GenericConv1D_Mapper = NodeMapper(GenericConv1DParser(), BasicConv1DBindings) GenericDWConv1D_Mapper = NodeMapper(GenericDWConv1DParser(), [BasicDWConv1DBinding]) GenericConv2D_Mapper = NodeMapper(GenericConv2DParser(), BasicConv2DBindings) GenericDWConv2D_Mapper = NodeMapper(GenericDWConv2DParser(), BasicDWConv2DBindings) diff --git a/DeeployTest/Tests/Autoencoder1D/inputs.npz b/DeeployTest/Tests/Autoencoder1D/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..cc639dab2fec2f3ad9c506540268ae2edfaab71f GIT binary patch literal 344974 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

&j-9{CLF_FREn(NT^a7Q&e~ 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 z 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ⅅG0 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

UcrJ|1-KOBuWjYx3aRtoN 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 literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/Autoencoder1D/outputs.npz b/DeeployTest/Tests/Autoencoder1D/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..13e8f46fada8d2941b0a265237c091e07bd98611 GIT binary patch literal 1290 zcmbVMYfzL06kQ%Vh60A$Cg|Eq8>|T=Zy($*Qh{}rU6;3_sDNx{3bYFd60{;hh#HFW zR6#~ZOF>3aP`Sr&5GBzOS24xF96@|EIX<#xY>3q#{pwHW&N+APx%b!oakMHcYq97p zrixw+Hpz|FB9WOkBC#kXJuNjo%_BKA%R)5%jcdL%Z_OyxM5(olEkqfjY}b`ZhD5#V zY?*6-&d1eF=Bi84r|IL9m#64gCYk-<_%(*45#O*XJ~e4%R(QI}JpIg^<|fOL{U6x4 zmIc7}&k*#g1l&Ep0JjEJD69>_oyQT-Jn@0?U^rSfeu~&NQE)C)qOnzrWu`#f>xzcu zvJlu++~E5s26?!>nceme^EvTtj!XE3`>oq}wDtm*v|Z)%=?{7AY!e%sAF(fPak6I* z@2+8t+)GaCCOSH)jkV>BHXX>!}Dqt_C57ROmi@nEe^!=CKVEN{`j^^4VwUO z*j^0*miwa9d*rv%{UK=$!aMHMAhpcp$fdjaT4e(Ka;TcieywMSYWTgf1MG9^2ul>jf^BiR@Ni(eaPD%sFzIBeV9KcwUa#IJ z=wv$ug|0;Ca4i?IcI*;NA5{uUL#g0sRW3~5S1FVnsS=z|$wEl=Q zZ67_Cd_$&CT$+I*6(3Vyk(L?@#iSTJkGvdZG|fabCB~85X$Fn43T8)BI2Yx(b5^y6 zyS~ok+&@-wzRT~e_VfMOA#*A#BJ;UDbQWuuByw|d2z$3K=FF{1_NtBIQQLxWw@ZzN zb-plV#GuzF2%bk5VwE8f^`XHycyAuUri4Nn9D>dvEfN+55=#nX6s)N#OjuQ4?B+Gb^=(7vtvhEaB2VSANl%MHB ztQ^K?_DG15qM~>_`nJlU*k+53204DxSmFM_hqyD@4sB;9Be8e_da6Fa?S6Y~`f@Us zN6VlKF5rOQZgOo^19xohX61upY|q{NV9{Bw-`mSu3@15a&J8|T-NmKfU*n6f+PHL} zn;oBaazNydT;`C0qWl7MJ7+_9UWB^zJhZRffH@r-kmsF`>(;q&uPKDryWgOQ3lXp< z4?X$Z!Nt{%cWDN_mHl#fE@nTQ`Mmbbn}xEQfjj)wj_rJ zJF}@csDNhWgpsdjF&)|zO{yJ{%#q&uCeQu> DXU8(Q literal 0 HcmV?d00001 diff --git a/TargetLibraries/Generic/inc/DeeployBasicMath.h b/TargetLibraries/Generic/inc/DeeployBasicMath.h index f647c833e0..288cb419ac 100644 --- a/TargetLibraries/Generic/inc/DeeployBasicMath.h +++ b/TargetLibraries/Generic/inc/DeeployBasicMath.h @@ -22,6 +22,7 @@ #include #include + #include #include #include @@ -31,6 +32,8 @@ #include "types.h" #include "utils.h" +#include "kernel/BatchNorm.h" +#include "kernel/ConvTranspose1d_fp32.h" #include "kernel/Convolution.h" #include "kernel/DWConvolution.h" #include "kernel/Div.h" @@ -40,10 +43,12 @@ #include "kernel/Layernorm.h" #include "kernel/MatMul.h" #include "kernel/MaxPool.h" +#include "kernel/MaxPool1d.h" #include "kernel/RMSNorm.h" #include "kernel/RQDiv.h" #include "kernel/RQGELU.h" #include "kernel/RQHardswish.h" +#include "kernel/Relu.h" #include "kernel/RequantShift.h" #include "kernel/Softmax.h" diff --git a/TargetLibraries/Generic/inc/kernel/BatchNorm.h b/TargetLibraries/Generic/inc/kernel/BatchNorm.h new file mode 100644 index 0000000000..72703f5fe2 --- /dev/null +++ b/TargetLibraries/Generic/inc/kernel/BatchNorm.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef BATCHNORM_H +#define BATCHNORM_H + +#include +#include + +void BatchNorm_fp32(const float32_t *input, const float32_t *gamma, + const float32_t *beta, const float32_t *mean, + const float32_t *var, float32_t *output, int N, int C, + int L); + +#endif // BATCHNORM_H diff --git a/TargetLibraries/Generic/inc/kernel/ConvTranspose1d_fp32.h b/TargetLibraries/Generic/inc/kernel/ConvTranspose1d_fp32.h new file mode 100644 index 0000000000..40ef065992 --- /dev/null +++ b/TargetLibraries/Generic/inc/kernel/ConvTranspose1d_fp32.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef CONV_TRANSPOSE1D_FP32_H +#define CONV_TRANSPOSE1D_FP32_H + +#include +#include + +void ConvTranspose1d_fp32(const float32_t *input, uint32_t C_in, uint32_t W_in, + const float32_t *weight, uint32_t C_out, uint32_t K, + uint32_t stride, const float32_t *bias, bool has_bias, + float32_t *output, uint32_t W_out); + +#endif // CONV_TRANSPOSE1D_FP32_H diff --git a/TargetLibraries/Generic/inc/kernel/Convolution.h b/TargetLibraries/Generic/inc/kernel/Convolution.h index f86e8dcd75..8c1d2388ba 100644 --- a/TargetLibraries/Generic/inc/kernel/Convolution.h +++ b/TargetLibraries/Generic/inc/kernel/Convolution.h @@ -43,4 +43,13 @@ void Conv2d_fp32_fp32_fp32_NCHW(const float *__restrict__ pSrcA, uint32_t C, uint32_t SQ, const float *__restrict__ pSrcBias, const bool has_bias, float *__restrict__ pDstC); +void Conv1d_fp32_fp32_fp32( + const float32_t *__restrict__ pSrcA, // Input: [C_in, W_in] + uint32_t C_in, uint32_t W_in, + const float32_t *__restrict__ pSrcB, // Weights: [C_out, C_in, K] + uint32_t C_out, uint32_t K, uint32_t stride, + const float32_t *__restrict__ pSrcBias, const bool has_bias, + float32_t *__restrict__ pDstC, // Output: [C_out, W_out] + uint32_t W_out); + #endif //__DEEPLOY_BASIC_MATH_CONVOLUTION_KERNEL_HEADER_ diff --git a/TargetLibraries/Generic/inc/kernel/MaxPool1d.h b/TargetLibraries/Generic/inc/kernel/MaxPool1d.h new file mode 100644 index 0000000000..26d5e8e460 --- /dev/null +++ b/TargetLibraries/Generic/inc/kernel/MaxPool1d.h @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef __DEEPLOY_BASIC_MATH_MAXPOOL1D_KERNEL_HEADER_ +#define __DEEPLOY_BASIC_MATH_MAXPOOL1D_KERNEL_HEADER_ + +#include "DeeployBasicMath.h" + +void MaxPool1d_fp32_fp32(float32_t const *__restrict__ pSrcA, uint32_t C, + uint32_t W, uint32_t K, uint32_t S, + float32_t *__restrict__ pDstC); + +#endif \ No newline at end of file diff --git a/TargetLibraries/Generic/src/BatchNorm_fp32.c b/TargetLibraries/Generic/src/BatchNorm_fp32.c new file mode 100644 index 0000000000..9b30a30207 --- /dev/null +++ b/TargetLibraries/Generic/src/BatchNorm_fp32.c @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#include "DeeployBasicMath.h" + +void BatchNorm_fp32(const float32_t *input, const float32_t *gamma, + const float32_t *beta, const float32_t *mean, + const float32_t *var, float32_t *output, int N, int C, + int L) { + const float epsilon = 1e-5f; +#pragma omp parallel for + for (int c = 0; c < C; ++c) { + float32_t c_mean = mean[c]; + float32_t c_var = var[c]; + float32_t c_gamma = gamma[c]; + float32_t c_beta = beta[c]; + float32_t denom = sqrtf(c_var + epsilon); + for (int n = 0; n < N; ++n) { + for (int l = 0; l < L; ++l) { + int index = n * C * L + c * L + l; + float32_t x = input[index]; + float32_t norm = (x - c_mean) / denom; + output[index] = c_gamma * norm + c_beta; + } + } + } +} diff --git a/TargetLibraries/Generic/src/ConvTranspose1d_fp32.c b/TargetLibraries/Generic/src/ConvTranspose1d_fp32.c new file mode 100644 index 0000000000..362058734e --- /dev/null +++ b/TargetLibraries/Generic/src/ConvTranspose1d_fp32.c @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#include "DeeployBasicMath.h" + +void ConvTranspose1d_fp32(const float32_t *input, uint32_t C_in, uint32_t W_in, + const float32_t *weight, uint32_t C_out, uint32_t K, + uint32_t stride, const float32_t *bias, bool has_bias, + float32_t *output, uint32_t W_out) { + /* + input: [C_in, W_in] + weight: [C_in, C_out, K] + output: [C_out, W_out] + bias: [C_out] optionally + + */ + + // Output initialization + for (uint32_t c = 0; c < C_out; ++c) { + for (uint32_t w = 0; w < W_out; ++w) { + output[c * W_out + w] = 0.0f; + } + } + + // For each output channel + for (uint32_t cout = 0; cout < C_out; ++cout) { + // For each input channel + for (uint32_t cin = 0; cin < C_in; ++cin) { + // For each input width + for (uint32_t w_in = 0; w_in < W_in; ++w_in) { + float32_t val = input[cin * W_in + w_in]; + // Transposed convolution: output width is calculated based on stride + for (uint32_t k = 0; k < K; ++k) { + uint32_t w_out = w_in * stride + k; + if (w_out < W_out) { + // weight indexing: weight[cin, cout, k] + float32_t wgt = weight[cin * (C_out * K) + cout * K + k]; + output[cout * W_out + w_out] += val * wgt; + } + } + } + } + if (has_bias) { + for (uint32_t w = 0; w < W_out; ++w) { + output[cout * W_out + w] += bias[cout]; + } + } + } +} diff --git a/TargetLibraries/Generic/src/Convolution_fp32.c b/TargetLibraries/Generic/src/Convolution_fp32.c index 172749bce2..e073e18125 100644 --- a/TargetLibraries/Generic/src/Convolution_fp32.c +++ b/TargetLibraries/Generic/src/Convolution_fp32.c @@ -66,3 +66,32 @@ void Conv2d_fp32_fp32_fp32_NCHW(const float32_t *__restrict__ pSrcA, uint32_t C, } } } + +void Conv1d_fp32_fp32_fp32( + const float32_t *__restrict__ pSrcA, // Input: [C_in, W_in] + uint32_t C_in, uint32_t W_in, + const float32_t *__restrict__ pSrcB, // Weights: [C_out, C_in, K] + uint32_t C_out, uint32_t K, uint32_t stride, + const float32_t *__restrict__ pSrcBias, const bool has_bias, + float32_t *__restrict__ pDstC, // Output: [C_out, W_out] + uint32_t W_out) { + uint32_t c_out, c_in, w_out, k, w_in; + for (c_out = 0; c_out < C_out; ++c_out) { + for (w_out = 0; w_out < W_out; ++w_out) { + float32_t sum = 0.0f; + for (c_in = 0; c_in < C_in; ++c_in) { + for (k = 0; k < K; ++k) { + w_in = w_out * stride + k; + if (w_in < W_in) { + sum += pSrcA[c_in * W_in + w_in] * + pSrcB[c_out * C_in * K + c_in * K + k]; + } + } + } + if (has_bias) { + sum += pSrcBias[c_out]; + } + pDstC[c_out * W_out + w_out] = sum; + } + } +} \ No newline at end of file diff --git a/TargetLibraries/Generic/src/MaxPool1D_fp32.c b/TargetLibraries/Generic/src/MaxPool1D_fp32.c new file mode 100644 index 0000000000..a8686503b4 --- /dev/null +++ b/TargetLibraries/Generic/src/MaxPool1D_fp32.c @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +// +// SPDX-License-Identifier: Apache-2.0 + +#include "DeeployBasicMath.h" +#include + +void MaxPool1d_fp32_fp32(float32_t const *__restrict__ pSrcA, uint32_t C, + uint32_t W, uint32_t K, uint32_t S, + float32_t *__restrict__ pDstC) { + uint32_t W_out = (W - K) / S + 1; + for (uint32_t c = 0; c < C; ++c) { + for (uint32_t w_out = 0; w_out < W_out; ++w_out) { + float32_t max = -INFINITY; + for (uint32_t k = 0; k < K; ++k) { + uint32_t w_in = w_out * S + k; + if (w_in >= W) + continue; + float32_t tmp = pSrcA[c * W + w_in]; + if (tmp > max) { + max = tmp; + } + } + pDstC[c * W_out + w_out] = max; + } + } +} From cf691c42c793ae260c2c485eeb65ffe7bcb21bc3 Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Fri, 24 Oct 2025 16:26:04 +0200 Subject: [PATCH 13/28] Fix aliasing (#125) This PR gives a quick, not-super-optimal, but working, solution to the problem by implementing the aliasing information basically as a doubly-linked list. On a reshape, both input and output record each others name, and to check whether an alias is alive, we just traverse the aliasing double-linked list in all the directions with a bfs. Imo for our current cases this is good enough performance-wise since there usually aren't so many aliasing chains happening, so I don't want to invest more time in the performance aspect. As a bonus, I sprinkled a few refactors in there, the removal of bitrotten `fromVariableBuffer`s, refactor of `hoistConstant` to not use `fromVariableBuffer` (be careful with those shapes!), and refactor of TransientBuffer's `__init__` function to use its super's one (reuse and all that). ## Changed - Removed `fromVariableBuffer` - Refactored `hoistConstant` - Refactored TransientBuffer's `__init__` ## Fixed - Fixed aliasing --- CHANGELOG.md | 5 + .../MemoryAllocation.py | 2 +- Deeploy/DeeployTypes.py | 118 +++++------------- Deeploy/Targets/Generic/Parsers.py | 34 +---- .../Generic/Templates/ReshapeTemplate.py | 13 +- 5 files changed, 50 insertions(+), 122 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 158138ccf4..9c82f50bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Fix aliasing [#125](https://github.com/pulp-platform/Deeploy/pull/125) - Support for 1D Autoencoder [#98](https://github.com/pulp-platform/Deeploy/pull/98) - Refactor Logging for Improved Debugging [#115](https://github.com/pulp-platform/Deeploy/pull/115) - Add reuse-tool as an SPDX license header linter [#113](https://github.com/pulp-platform/Deeploy/pull/113) @@ -74,6 +75,9 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Changed types and added correct casts to fix many compiler warnings in the PULP target library - Use [reuse-tool](https://github.com/fsfe/reuse-tool) in pre-commit, CI, and Makefile for SPDX license header linting - Deployer workflow now uses `prepare(...)` instead of `generateFunction(...)`. +- Removed `fromVariableBuffer` +- Refactored `hoistConstant` +- Refactored TransientBuffer's `__init__` ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon @@ -84,6 +88,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Corrected method usage in `importDeeployState` to call `NetworkContext.importNetworkContext` instead of the incorrect method name - Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` - Fixed `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) +- Fixed aliasing ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py index b73fcafe31..f10d333502 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/MemoryAllocation.py @@ -141,7 +141,7 @@ def apply(self, assert buffer._live == True, f"Tried to deallocate already dead buffer {buffer.name}" buffer._live = False # Don't deallocate if it's an alias of a live buffer - if not buffer.has_live_ancestors(ctxt = ctxt): + if not buffer.has_live_aliases(ctxt): memoryLevel = "None" if not hasattr(buffer, "_memoryLevel") else buffer._memoryLevel if memoryLevel not in ctxt._dynamicSize: ctxt._dynamicSize[memoryLevel] = 0 diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index e6ca25c9bd..936931c2e6 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -238,7 +238,7 @@ class VariableBuffer(): allocTemplate: NodeTemplate #: NodeTemplate: Holds the buffer's allocation code deallocTemplate: NodeTemplate #: NodeTemplate: Holds the buffer's deallocation code - def __init__(self, name: str = '', shape = [1], alias_of: Optional[List[str]] = []): + def __init__(self, name: str = '', shape = [1], aliases: Optional[List[str]] = None): self.name: str = name #: str: Canonical name that this buffer is registered as in the NetworkContext self.shape: Sequence[ int] = shape #: Sequence[int]: Represents the dimensions of the underlying tensor as a sequence of dimension sizes @@ -257,7 +257,7 @@ def __init__(self, name: str = '', shape = [1], alias_of: Optional[List[str]] = self.is_input: bool = False self.is_output: bool = False - self.alias_of: List[str] = alias_of if alias_of is not None else [] + self.aliases: Set[str] = set(aliases) if aliases is not None else set() def _bufferRepresentation(self) -> Dict: return {"type": self._instance, "name": self.name, "size": int(np.prod(self.shape))} @@ -324,42 +324,7 @@ def __getstate__(self): def fromNode(cls, node: gs.Node): return (cls(name = node.name, shape = node.shape if not isinstance(node, gs.Constant) else node.values.shape)) - def add_aliases(self, aliases_to_add: List[str]): - """ - Adds list of aliases to the alias_of attribute. - Parameters - ---------- - alias_to_add : List[str] - List of names of aliases to add to the alias_of attribute. - Returns - ------- - None - """ - - if not hasattr(self, "alias_of"): - return None - - for alias in aliases_to_add: - if alias not in self.alias_of: - self.alias_of.append(alias) - - return None - - def get_aliases_of(self): - """ - Getter function for the alias_of attribute. - Returns - ------- - List[str] - List of names o all aliases of this VariableBuffer. - """ - - if hasattr(self, "alias_of"): - return self.alias_of - else: - return list() - - def has_live_ancestors(self, ctxt: NetworkContext) -> bool: + def has_live_aliases(self, ctxt: NetworkContext) -> bool: """Checks whether this VariableBuffer has any live ancestors, i.e. buffers that are still live and are aliased by this buffer. Parameters ---------- @@ -370,14 +335,18 @@ def has_live_ancestors(self, ctxt: NetworkContext) -> bool: bool True if this VariableBuffer has any live ancestors, False otherwise """ - if not hasattr(self, "alias_of"): - return False - - for alias in self.alias_of: - if ctxt.lookup(alias)._live: - return True - - return False + # Do a breadth-first search across the aliasing double-linked list + live = self._live + queue = set(self.aliases) + visited = set(self.name) + while len(queue) > 0: + next = queue.pop() + buffNext = ctxt.lookup(next) + assert isinstance(buffNext, VariableBuffer) + live |= buffNext._live + visited.add(next) + queue |= buffNext.aliases - visited + return live def sizeInBytes(self) -> int: """Returns the size of this VariableBuffer in bytes @@ -398,28 +367,13 @@ class TransientBuffer(VariableBuffer): """ def __init__(self, name: str = '', size = 0): - self.name = name - self.size = size #: int: Total BYTE size of this TransientBuffer - - # Do not override - Should be written in the parsing passes - self._users = [] + super().__init__(name, shape = (size,)) # Do not override - Should be written in the parsing passes self._type: Type[Pointer] = PointerClass(VoidType) - - # Do not override - Should be written in the deployment passes - self._live = False - - # Do not override - Set in Templates depending on platform - self._deploy = True - - self.is_input: bool = False - self.is_output: bool = False - - self.alias_of: List[str] = [] + self.size = size def __eq__(self, other): - ret = all([self.name == other.name, self.size == other.size]) return ret @@ -432,10 +386,6 @@ def __str__(self) -> str: def __repr__(self) -> str: return f'TransientBuffer: name: {self.name}, size: {self.size}' - @classmethod - def fromVariableBuffer(cls, buffer: VariableBuffer): - ret = cls(name = buffer.name, size = np.prod(buffer.shape) * buffer._type.typeWidth // 8) - def sizeInBytes(self) -> int: return int(self.size) @@ -479,12 +429,6 @@ def __repr__(self) -> str: def _bufferRepresentation(self) -> Dict: return {"type": self._type, "name": self.name, "size": int(np.prod(self.shape)), "values": self._valueString()} - @classmethod - def fromVariableBuffer(cls, buffer: VariableBuffer, values): - ret = cls(name = buffer.name, shape = buffer.shape, values = values) - - return ret - class StructBuffer(VariableBuffer): """Class to represent Struct object needed by the generated C Code @@ -999,12 +943,15 @@ def hoistReference(self, ref._instance = ref._type(name, ctxt = self) return ref - def hoistConstant(self, node: gs.Node, name: str = '', _type: Optional[Type[Pointer]] = None) -> str: - """Register a ConstantBuffer extracted directly from a graphsurgeon Node + def hoistConstant(self, + constant: gs.Constant, + name: Optional[str] = None, + _type: Optional[Type[Pointer]] = None) -> str: + """Register a ConstantBuffer extracted directly from a graphsurgeon Constant Parameters ---------- - node : gs.Node + constant : gs.Constant graphsurgeon.Node containing a single constant output name : str Name of the ConstantBuffer to be registered @@ -1017,21 +964,18 @@ def hoistConstant(self, node: gs.Node, name: str = '', _type: Optional[Type[Poin Returns the name of the newly registed ConstantBuffer """ + assert len(constant.outputs) <= 1, f"Constant {constant.name} has more than one output" - assert len(node.outputs) <= 1, f"Constant {node.name} has more than one output" + name = name if name is not None else constant.name - if name == "": - name = node.name + # LMACAN: The shape needs to be copied into a tuple for pickling to work. Don't ask me why.. + buffer = self.ConstantBuffer(name, tuple(constant.shape), constant.values) + self.add(buffer, 'global') - # SCHEREMO: This is currently heuristic, but should be annotated in ONNX - localBuffer = self.VariableBuffer.fromNode(node = node) - globalBuffer = self.ConstantBuffer.fromVariableBuffer(localBuffer, values = node.values) - globalBuffer.name = name - globalBuffer._type = _type + if _type is not None: + self.annotateType(name, _type) - self.add(globalBuffer, 'global') - - return globalBuffer.name + return name def addUser(self, name: str, node: gs.Node): """Adds an operator's name to the _user list of a VariableBuffer in the context diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index adc48ffe15..7752834c50 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -1059,44 +1059,18 @@ def parseNodeCtxt(self, class ReshapeParser(NodeParser): - def __init__(self): - super().__init__() - def parseNode(self, node: gs.Node) -> (bool): - ret = all([len(node.inputs) == 2, len(node.outputs) == 1]) - return ret def parseNodeCtxt(self, ctxt: NetworkContext, node: gs.Node, channels_first: bool = True) -> Tuple[NetworkContext, bool]: - - # Define names of node inputs and outputs, according to the ONNX standard - inputs = ['data_in', 'shape'] - outputs = ['data_out'] - - # Map inputs and outputs to their corresponding names in the operator representation - for idx, inputNode in enumerate(node.inputs): - self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name - for idx, outputNode in enumerate(node.outputs): - self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name - - # Update alias_of parameter for the output node - output_node = ctxt.lookup(node.outputs[outputs.index("data_out")].name) - input_node = ctxt.lookup(node.inputs[inputs.index("data_in")].name) - - # Prepare new aliases - new_output_node_aliases = input_node.get_aliases_of() - new_output_node_aliases.append(input_node.name) - - # Add new aliases - output_node.add_aliases(aliases_to_add = new_output_node_aliases) - - # Compute data size - self.operatorRepresentation['size'] = np.prod(ctxt.lookup(node.inputs[0].name).shape) - + for tensor, symName in zip(node.inputs, ['data_in', 'shape']): + self.operatorRepresentation[symName] = ctxt.lookup(tensor.name).name + for tensor, symName in zip(node.outputs, ['data_out']): + self.operatorRepresentation[symName] = ctxt.lookup(tensor.name).name return ctxt, True diff --git a/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py b/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py index 1ba3d99655..15b7d64bef 100644 --- a/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py +++ b/Deeploy/Targets/Generic/Templates/ReshapeTemplate.py @@ -4,7 +4,7 @@ from typing import Dict, List, Tuple -from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation +from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer class _ReshapeTemplate(NodeTemplate): @@ -25,9 +25,14 @@ def alignToContext(self, ctxt: NetworkContext, ctxt.globalObjects[operatorRepresentation["shape"]]._deploy = False ctxt.globalObjects[operatorRepresentation["shape"]]._live = False - inBuffer = ctxt.lookup(operatorRepresentation['data_in']) - outBuffer = ctxt.lookup(operatorRepresentation['data_out']) - outBuffer._alias = inBuffer.name + bufferIn = ctxt.lookup(operatorRepresentation['data_in']) + assert isinstance(bufferIn, VariableBuffer) + bufferOut = ctxt.lookup(operatorRepresentation['data_out']) + assert isinstance(bufferOut, VariableBuffer) + + # Link aliases to each buffer + bufferIn.aliases.add(bufferOut.name) + bufferOut.aliases.add(bufferIn.name) return ctxt, operatorRepresentation, [] From f905830a04a343fa3cd2d886c754d8def3287158 Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Fri, 24 Oct 2025 22:55:08 +0200 Subject: [PATCH 14/28] Fix missing const's layout transformation and refactor NCHWtoNHWC passes (#122) The NCHWtoNHWC passes were missing the layout transformation of the bias (in the `Conv` case) or mul/add/shift (in the `RequantizedConv` case). In the process of adding that I refactored the passes in general. ## Changed - refactor of NCHWtoNHWC passes ## Fixed - missing layout transformation of the const's (bias, mul, add, shift in Conv/RequantizedConv) --- CHANGELOG.md | 3 + .../LoweringOptimizationPasses.py | 530 +++++++----------- Deeploy/Targets/Neureka/Deployer.py | 4 +- 3 files changed, 211 insertions(+), 326 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c82f50bb9..67a3684c82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Fix missing const's layout transformation and refactor NCHWtoNHWC passes [#122](https://github.com/pulp-platform/Deeploy/pull/122) - Fix aliasing [#125](https://github.com/pulp-platform/Deeploy/pull/125) - Support for 1D Autoencoder [#98](https://github.com/pulp-platform/Deeploy/pull/98) - Refactor Logging for Improved Debugging [#115](https://github.com/pulp-platform/Deeploy/pull/115) @@ -78,6 +79,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Removed `fromVariableBuffer` - Refactored `hoistConstant` - Refactored TransientBuffer's `__init__` +- Refactor of the NCHWtoNHWC passes ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon @@ -89,6 +91,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` - Fixed `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) - Fixed aliasing +- Missing layout transformation of the const's (bias, mul, add, shift in Conv/RequantizedConv) ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py index 7ef9e96ef0..a87a641d30 100644 --- a/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py +++ b/Deeploy/CommonExtensions/OptimizationPasses/TopologyOptimizationPasses/LoweringOptimizationPasses.py @@ -3,17 +3,36 @@ # SPDX-License-Identifier: Apache-2.0 from functools import partial -from typing import Iterable, List, Optional, Sequence, Tuple, TypeVar, Union +from typing import List, Optional, Sequence, Tuple, TypeVar, Union import numpy as np import onnx_graphsurgeon as gs -from Deeploy.CommonExtensions.OptimizationPasses.Matchers import Match +from Deeploy.CommonExtensions.OptimizationPasses.Matchers import Match, NonBranchingMatcher from Deeploy.CommonExtensions.OptimizationPasses.PassClasses import ReplaceSequentialPatternPass, SequentialPass, \ contextagnostic from Deeploy.TilingExtension.TilingCodegen import HyperRectangle +def _singleNodePattern(op: str) -> gs.Graph: + tensorIn = gs.Variable("input") + tensorOut = gs.Variable("output") + node = gs.Node(op = op, name = "node", inputs = [tensorIn], outputs = [tensorOut]) + graph = gs.Graph([node], inputs = [tensorIn], outputs = [tensorOut]) + return graph + + +def _isDepthwise(node: gs.Node) -> bool: + if node.op not in ["Conv", "RequantizedConv"]: + return False + + channels_first = node.attrs.get("channels_first", True) + spatialDims = len(node.inputs[1].shape) - 2 + shapeIn = node.inputs[0].shape + chIn = shapeIn[-spatialDims - 1] if channels_first else shapeIn[-1] + return chIn != 1 and node.attrs.get("group", 1) == chIn + + def _createReshape(tensorIn: gs.Tensor, name: str, newShape: Sequence[Union[int, str]], @@ -86,29 +105,27 @@ def _prependSqueezeDims(tensor: gs.Tensor, name: str, axis: Union[int, Sequence[ # Permute (0,1,2,3,...,N-2,N-1) -> (0,1,2,3,...,N-1,N-2) -def _permutationLastTwoDims(N: int) -> List[int]: +def _swapLastTwoDimsPermutation(N: int) -> List[int]: assert N >= 2, "N needs to be larger then 2" - return list(range(N - 2)) + [N - 1, N - 2] + return [*range(N - 2), N - 1, N - 2] -# Permute (0,1,2,3,...,N-1) -> (0,2,3,...,N-1,1) -def _permutationNCHWtoNHWC(N: int) -> List[int]: - assert N >= 3, "N needs to be larger then 3 for this to make any sense" - return [0] + list(range(2, N)) + [1] - - -# Permute (0,1,2,3,...,N-1) -> (0,N-1,1,2,3,...,N-2) -def _permutationNHWCtoNCHW(N: int) -> List[int]: - assert N >= 3, "N needs to be larger then 3 for this to make any sense" - return [0, N - 1] + list(range(1, N - 1)) +# Permute channels first <-> channels last: +# (*, ch, *) <-> (*, *, ch) +def _transformLayoutPermutation(dims: int, spatialDims: int, targetChannelsFirst: bool) -> List[int]: + batchDims = dims - spatialDims - 1 + if targetChannelsFirst: + ch = dims - 1 + nonBatchPerm = [ch, *range(batchDims, ch)] + else: + ch = batchDims + nonBatchPerm = [*range(ch + 1, dims), ch] + return list(range(batchDims)) + nonBatchPerm # Calculate permutation q = p^(-1) s.t. q(p(i)) = i -def _invertPermutation(permutation: List[int]) -> List[int]: - inverse = [0] * len(permutation) - for idx, permIdx in enumerate(permutation): - inverse[permIdx] = idx - return inverse +def _invertPermutation(permutation: Sequence[int]) -> List[int]: + return [permutation.index(i) for i in range(len(permutation))] T = TypeVar('T') @@ -124,78 +141,69 @@ def _permuteHyperRectangle(rect: HyperRectangle, permutation: List[int]) -> Hype return HyperRectangle(tuple(_permute(rect.offset, permutation)), tuple(_permute(rect.dims, permutation))) -def _prependTransposeNode(anchor: gs.Variable, - nodeName: str, - permutation: Iterable[int], - invert: bool = False) -> Tuple[gs.Node, gs.Variable]: - - if invert: - outShape = _permute(anchor.shape, _invertPermutation(permutation)) - else: - outShape = _permute(anchor.shape, permutation) - - anchorTransposeInput = gs.Variable(nodeName + "_Out", dtype = np.float32, shape = outShape) - anchorTransposeNode = gs.Node(name = nodeName, - op = "Transpose", - inputs = [anchorTransposeInput], - outputs = [anchor], - attrs = {'perm': permutation}) - - return anchorTransposeNode, anchorTransposeInput - - -def _appendTransposeNode(anchor: gs.Variable, - nodeName: str, - permutation: Iterable[int], - invert: bool = False) -> (gs.Node, gs.Variable): - - if invert: - outShape = _permute(anchor.shape, _invertPermutation(permutation)) - else: - outShape = _permute(anchor.shape, permutation) - - anchorTransposeOutput = gs.Variable(nodeName + "_In", dtype = np.float32, shape = outShape) - anchorTransposeNode = gs.Node(name = nodeName, - op = "Transpose", - inputs = [anchor], - outputs = [anchorTransposeOutput], - attrs = {'perm': permutation}) - - return anchorTransposeNode, anchorTransposeOutput +def _prependTranspose(tensor: gs.Variable, prevNode: gs.Node, perm: List[int]) -> gs.Node: + prevNodeTensorIdx = prevNode.outputs.index(tensor) + preTransposeTensor = gs.Variable(f"{prevNode.name}_{tensor.name}_pre_transposed", tensor.dtype, + _permute(tensor.shape, _invertPermutation(perm))) + transposeNode = gs.Node(op = "Transpose", + name = f"{prevNode.name}_{tensor.name}_pre_transpose", + attrs = {"perm": perm}, + inputs = [preTransposeTensor], + outputs = [tensor]) + prevNode.outputs[prevNodeTensorIdx] = preTransposeTensor + return transposeNode + + +def _appendTranspose(tensor: gs.Variable, nextNode: gs.Node, perm: List[int]) -> gs.Node: + nextNodeTensorIdx = nextNode.inputs.index(tensor) + transposedTensor = gs.Variable(f"{nextNode.name}_{tensor.name}_transposed", tensor.dtype, + _permute(tensor.shape, perm)) + transposeNode = gs.Node(op = "Transpose", + name = f"{nextNode.name}_{tensor.name}_transpose", + attrs = {"perm": perm}, + inputs = [tensor], + outputs = [transposedTensor]) + nextNode.inputs[nextNodeTensorIdx] = transposedTensor + return transposeNode + + +def _transformLayoutConst(const: gs.Constant, spatialDims: int, targetChannelsFirst: bool) -> None: + assert isinstance(const, gs.Constant) + if len(const.shape) < 2: + return + perm = _transformLayoutPermutation(len(const.shape), spatialDims, targetChannelsFirst) + const.values = const.values.transpose(perm) + + +def _transformLayoutDwWeightConst(const: gs.Constant, targetChannelsFirst: bool) -> None: + assert not targetChannelsFirst, "Target layout should be channels_last!" + assert isinstance(const, gs.Constant) + dims = len(const.shape) + perm = [*range(1, dims), 0] + const.values = const.values.transpose(perm) def _transposeMatMulInputs_fun(graph: gs.Graph, match: Match, name: str): + node = next(iter((match.nodes_map.values()))) - matched_nodes = [m for k, m in match.nodes_map.items()] - gemmNode = matched_nodes[0] - - inputA = gemmNode.inputs[0] - inputB = gemmNode.inputs[1] - - if 'transA' not in gemmNode.attrs: - gemmNode.attrs['transA'] = 0 - if 'transB' not in gemmNode.attrs: - gemmNode.attrs['transB'] = 0 - if 'alpha' not in gemmNode.attrs: - gemmNode.attrs['alpha'] = 1.0 - if 'beta' not in gemmNode.attrs: - gemmNode.attrs['beta'] = 1.0 + node.attrs['transA'] = node.attrs.get('transA', 0) + node.attrs['transB'] = node.attrs.get('transB', 0) + node.attrs['alpha'] = node.attrs.get('alpha', 1.0) + node.attrs['beta'] = node.attrs.get('beta', 1.0) # Prepend transpose on A if it's transposed - if gemmNode.attrs['transA'] != 0: - anchorTransposeNode, anchorTransposeOutput = _appendTransposeNode(inputA, name + "_A", - _permutationLastTwoDims(len(inputA.shape))) - gemmNode.inputs[0] = anchorTransposeOutput - gemmNode.attrs['transA'] = 0 - graph.nodes.append(anchorTransposeNode) + if node.attrs['transA'] == 1: + tensorA = node.inputs[0] + perm = _swapLastTwoDimsPermutation(len(tensorA.shape)) + graph.nodes.append(_appendTranspose(tensorA, node, perm)) + node.attrs['transA'] = False # Prepend transpose on B if it's not transposed - if gemmNode.attrs['transB'] != 1: - anchorTransposeNode, anchorTransposeOutput = _appendTransposeNode(inputB, name + "_B", - _permutationLastTwoDims(len(inputB.shape))) - gemmNode.inputs[1] = anchorTransposeOutput - gemmNode.attrs['transB'] = 1 - graph.nodes.append(anchorTransposeNode) + if node.attrs['transB'] == 0: + tensorB = node.inputs[1] + perm = _swapLastTwoDimsPermutation(len(tensorB.shape)) + graph.nodes.append(_appendTranspose(tensorB, node, perm)) + node.attrs['transB'] = True return graph @@ -206,62 +214,40 @@ def _transposeMatMulInputs_fun(graph: gs.Graph, match: Match, name: str): class TransposeMatmulInputsPass(ReplaceSequentialPatternPass): def __init__(self): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['gemmOut'], op = 'RequantizedGemm', name = 'requantizedGemm') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern("RequantizedGemm") name = "_TRANSPOSE_MATMUL_INPUTS_PASS" super().__init__(graph, _transposeMatMulInputs_fun, name) def _NCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool = True): + node = next(iter((match.nodes_map.values()))) - matched_nodes = [m for k, m in match.nodes_map.items()] - opNode = matched_nodes[0] - node_op = opNode.op - - # Default for non-existent channels_first: True - channels_first = opNode.attrs["channels_first"] if "channels_first" in opNode.attrs else True - + channels_first = node.attrs.get("channels_first", True) if (channels_first != default_channels_first): + tensorIn = node.inputs[0] + tensorOut = node.outputs[0] - inputNode = opNode.inputs[0] - outputNode = opNode.outputs[0] - - inPermute = _permutationNCHWtoNHWC(len(inputNode.shape)) - outPermute = _permutationNHWCtoNCHW(len(outputNode.shape)) - - inputTransposeNode, inputTransposeOutput = _appendTransposeNode(inputNode, name + "_TransposeIn", inPermute) - outputTransposeNode, outputTransposeInput = _prependTransposeNode(outputNode, - name + "_TransposeOut", - outPermute, - invert = True) - - opNode.inputs[0] = inputTransposeOutput - opNode.outputs[0] = outputTransposeInput - graph.nodes.append(inputTransposeNode) - graph.nodes.append(outputTransposeNode) - - if node_op in ["RequantizedConv", "Conv"]: + if node.op in ["RequantizedConv", "Conv"]: + spatialDims = len(node.inputs[1].shape) - 2 + elif node.op == "MaxPool": + spatialDims = len(node.attrs["kernel_shape"]) + elif node.op == "Pad": + spatialDims = 2 # Hack based on current status + else: + raise ValueError(f"Cannot determine spatialDims for node {node.name} with operator {node.op}") - # Non DW-Type: - if opNode.attrs['group'] == 1: - weightNode = opNode.inputs[1] - weightTransposeNode, weightTransposeOutput = _appendTransposeNode(weightNode, name + "TransposeWeight", - inPermute) + permuteIn = _transformLayoutPermutation(len(tensorIn.shape), spatialDims, default_channels_first) + graph.nodes.append(_appendTranspose(tensorIn, node, permuteIn)) - else: - DWPermute = [inPermute[-1]] + inPermute[1:-1] + [inPermute[0]] - weightNode = opNode.inputs[1] - weightTransposeNode, weightTransposeOutput = _appendTransposeNode(weightNode, name + "TransposeWeight", - DWPermute) + permuteOut = _transformLayoutPermutation(len(tensorOut.shape), spatialDims, channels_first) + graph.nodes.append(_prependTranspose(tensorOut, node, permuteOut)) - opNode.inputs[1] = weightTransposeOutput - graph.nodes.append(weightTransposeNode) + if node.op in ["Conv", "RequantizedConv"]: + # In the case of Conv: [weights, opt. bias], RequantizedConv: [weights, mul, add, opt. shift] + for tensor in node.inputs[1:]: + _transformLayoutConst(tensor, spatialDims, default_channels_first) - opNode.attrs["channels_first"] = default_channels_first + node.attrs["channels_first"] = default_channels_first return graph @@ -270,12 +256,7 @@ def _NCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_f class NCHWtoNHWCMaxPoolPass(ReplaceSequentialPatternPass): def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['maxPool'], op = 'MaxPool', name = 'MaxPool') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern(op = "MaxPool") name = "_NCHW_TO_NHWC_MAXPOOL_PASS" super().__init__(graph, partial(_NCHWtoNHWC_fun, default_channels_first = default_channels_first), name) @@ -284,214 +265,129 @@ def __init__(self, default_channels_first: bool = True): class NCHWtoNHWCConvPass(ReplaceSequentialPatternPass): def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'Conv', name = 'conv') - graph.outputs.append(output) - graph.inputs.append(_input) - - name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_NCHWtoNHWC_fun, default_channels_first = default_channels_first), name) - - -@contextagnostic -class NCHWtoNHWCRequantizedConvPass(ReplaceSequentialPatternPass): - - def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'RequantizedConv', name = 'requantizedConv') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern(op = "Conv|RequantizedConv") name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_NCHWtoNHWC_fun, default_channels_first = default_channels_first), name) + super().__init__(graph, partial(_NCHWtoNHWC_fun, default_channels_first = default_channels_first), name, + NonBranchingMatcher(regex_op = True)) @contextagnostic class NCHWtoNHWCPadPass(ReplaceSequentialPatternPass): def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['padOut'], op = 'Pad', name = 'pad') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern(op = "Pad") name = "_NCHW_TO_NHWC_PAD_PASS" super().__init__(graph, partial(_NCHWtoNHWC_fun, default_channels_first = default_channels_first), name) -@contextagnostic -class NCHWtoNHWCPass(SequentialPass): - - def __init__(self, default_channels_first: bool = True): - passes = [ - NCHWtoNHWCPadPass(default_channels_first), - NCHWtoNHWCMaxPoolPass(default_channels_first), - NCHWtoNHWCConvPass(default_channels_first), - NCHWtoNHWCRequantizedConvPass(default_channels_first), - ] - super().__init__(*passes) - - -def _PULPDWNCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool = True): - - matched_nodes = [m for k, m in match.nodes_map.items()] - opNode = matched_nodes[0] - node_op = opNode.op +def _NCWHtoNHWC_dw_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool) -> gs.Graph: + node = next(iter((match.nodes_map.values()))) - if opNode.attrs['group'] == 1: + if not _isDepthwise(node): return graph - if (("channels_first" in opNode.attrs and opNode.attrs["channels_first"] != default_channels_first) - or ("channels_first" not in opNode.attrs and default_channels_first == 0)): - - inputNode = opNode.inputs[0] - outputNode = opNode.outputs[0] + channels_first = node.attrs.get("channels_first", True) + if (channels_first != default_channels_first): + tensorIn = node.inputs[0] + tensorOut = node.outputs[0] - inPermute = _permutationNCHWtoNHWC(len(inputNode.shape)) - outPermute = _permutationNHWCtoNCHW(len(outputNode.shape)) + spatialDims = len(node.inputs[1].shape) - 2 - outputTransposeNode, outputTransposeInput = _prependTransposeNode(outputNode, - name + "_TransposeOut", - outPermute, - invert = True) + permuteIn = _transformLayoutPermutation(len(tensorIn.shape), spatialDims, default_channels_first) + permuteOut = _transformLayoutPermutation(len(tensorOut.shape), spatialDims, channels_first) - opNode.outputs[0] = outputTransposeInput - graph.nodes.append(outputTransposeNode) + graph.nodes.append(_appendTranspose(tensorIn, node, permuteIn)) + graph.nodes.append(_prependTranspose(tensorOut, node, permuteOut)) - if node_op == "RequantizedConv": + _transformLayoutDwWeightConst(node.inputs[1], default_channels_first) # weights - weightNode = opNode.inputs[1] - weightTransposeNode, weightTransposeOutput = _appendTransposeNode(weightNode, name + "TransposeWeight", - inPermute) - opNode.inputs[1] = weightTransposeOutput - graph.nodes.append(weightTransposeNode) + if len(node.inputs) > 2: + # In the case of Conv: [opt. bias], RequantizedConv: [mul, add, opt. shift] + for tensor in node.inputs[2:]: + _transformLayoutConst(tensor, spatialDims, default_channels_first) # bias - opNode.attrs["channels_first"] = default_channels_first + node.attrs["channels_first"] = default_channels_first return graph @contextagnostic -class PULPDWConvPass(ReplaceSequentialPatternPass): +class NCHWtoNHWCDwConvPass(ReplaceSequentialPatternPass): def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'RequantizedConv', name = 'requantizedConv') - graph.outputs.append(output) - graph.inputs.append(_input) + graph = _singleNodePattern(op = "Conv|RequantizedConv") + name = "_NCHW_TO_NHWC_DW_CONV_PASS" + super().__init__(graph, partial(_NCWHtoNHWC_dw_fun, default_channels_first = default_channels_first), name, + NonBranchingMatcher(regex_op = True)) - name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_PULPDWNCHWtoNHWC_fun, default_channels_first = default_channels_first), name) - - -def _PULPDenseNCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool = True): - matched_nodes = [m for k, m in match.nodes_map.items()] - opNode = matched_nodes[0] +def _PULP_NCHWtoNHWC_dw_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool = True): + node = next(iter((match.nodes_map.values()))) - node_group = opNode.attrs['group'] if 'group' in opNode.attrs else 1 - if node_group != 1: + if not _isDepthwise(node): return graph - return _NCHWtoNHWC_fun(graph, match, name, default_channels_first) - - -@contextagnostic -class PULPNCHWtoNHWCDenseRequantizedConvPass(ReplaceSequentialPatternPass): - - def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'RequantizedConv', name = 'requantizedConv') - graph.outputs.append(output) - graph.inputs.append(_input) - - name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_PULPDenseNCHWtoNHWC_fun, default_channels_first = default_channels_first), - name) - - -def _NeurekaDWNCHWtoNHWC_fun(graph: gs.Graph, match: Match, name: str, default_channels_first: bool = True): - - matched_nodes = [m for k, m in match.nodes_map.items()] - opNode = matched_nodes[0] + channels_first = node.attrs.get("channels_first", True) + if (channels_first != default_channels_first): + tensorOut = node.outputs[0] - node_group = opNode.attrs['group'] if 'group' in opNode.attrs else 1 - if node_group == 1: - return graph + spatialDims = len(node.inputs[1].shape) - 2 - return _NCHWtoNHWC_fun(graph, match, name, default_channels_first) + # LMACAN: PULP DW doesn't transpose the input + permuteOut = _transformLayoutPermutation(len(tensorOut.shape), spatialDims, channels_first) + graph.nodes.append(_prependTranspose(tensorOut, node, permuteOut)) -@contextagnostic -class NeurekaNCHWtoNHWCDWRequantizedConvPass(ReplaceSequentialPatternPass): + # RequantizedConv: [weights, mul, add, opt. shift] + for tensor in node.inputs[1:]: + _transformLayoutConst(tensor, spatialDims, default_channels_first) - def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'RequantizedConv', name = 'requantizedConv') - graph.outputs.append(output) - graph.inputs.append(_input) + node.attrs["channels_first"] = default_channels_first - name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_NeurekaDWNCHWtoNHWC_fun, default_channels_first = default_channels_first), - name) + return graph @contextagnostic -class PULPNCHWtoNHWCDenseConvPass(ReplaceSequentialPatternPass): +class PULPNCHWtoNHWCDwConvPass(ReplaceSequentialPatternPass): def __init__(self, default_channels_first: bool = True): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'Conv', name = 'conv') - graph.outputs.append(output) - graph.inputs.append(_input) - - name = "_NCHW_TO_NHWC_CONV_PASS" - super().__init__(graph, partial(_PULPDenseNCHWtoNHWC_fun, default_channels_first = default_channels_first), - name) + graph = _singleNodePattern(op = "RequantizedConv") + name = "_PULP_NCHW_TO_NHWC_DW_CONV_PASS" + super().__init__(graph, partial(_PULP_NCHWtoNHWC_dw_fun, default_channels_first = default_channels_first), name) @contextagnostic -class PULPNCHWtoNHWCPass(SequentialPass): +class NCHWtoNHWCPass(SequentialPass): def __init__(self, default_channels_first: bool = True): passes = [ NCHWtoNHWCPadPass(default_channels_first), NCHWtoNHWCMaxPoolPass(default_channels_first), - PULPDWConvPass(default_channels_first), - PULPNCHWtoNHWCDenseConvPass(default_channels_first), - PULPNCHWtoNHWCDenseRequantizedConvPass(default_channels_first), + NCHWtoNHWCDwConvPass(default_channels_first), + NCHWtoNHWCConvPass(default_channels_first), ] super().__init__(*passes) @contextagnostic -class NeurekaNCHWtoNHWCPass(SequentialPass): +class PULPNCHWtoNHWCPass(SequentialPass): def __init__(self, default_channels_first: bool = True): passes = [ NCHWtoNHWCPadPass(default_channels_first), NCHWtoNHWCMaxPoolPass(default_channels_first), - NeurekaNCHWtoNHWCDWRequantizedConvPass(default_channels_first), - PULPNCHWtoNHWCDenseConvPass(default_channels_first), - PULPNCHWtoNHWCDenseRequantizedConvPass(default_channels_first), + PULPNCHWtoNHWCDwConvPass(default_channels_first), + NCHWtoNHWCConvPass(default_channels_first), ] super().__init__(*passes) def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): - matched_nodes = list(match.nodes_map.values()) - requantizedGemm = matched_nodes[0] + node = next(iter((match.nodes_map.values()))) - matrixA: gs.Variable = requantizedGemm.inputs[0] - matrixB: gs.Constant = requantizedGemm.inputs[1] - matrixY: gs.Variable = requantizedGemm.outputs[0] + matrixA: gs.Variable = node.inputs[0] + matrixB: gs.Constant = node.inputs[1] + matrixY: gs.Variable = node.outputs[0] # Check matrixB is a constant, otherwise don't transform if not isinstance(matrixB, gs.Constant): @@ -506,10 +402,22 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): # Pointwise with HWC layout (channels_first == False) + # Defaults + node.attrs['transA'] = node.attrs.get('transA', 0) + node.attrs['transB'] = node.attrs.get('transB', 0) + node.attrs['alpha'] = node.attrs.get('alpha', 1.0) + node.attrs['beta'] = node.attrs.get('beta', 1.0) + # If transA is set then the matrix is of shape [B x K x M] and it needs to be transposed, otherwise its shape is [B x M x K] - if 'transA' in requantizedGemm.attrs and requantizedGemm.attrs['transA'] == 1: - matrixATransposeNode, matrixA = _appendTransposeNode(matrixA, name, _permutationLastTwoDims(len(matrixA.shape))) - graph.nodes.append(matrixATransposeNode) + if node.attrs['transA'] == 1: + perm = _swapLastTwoDimsPermutation(len(matrixA.shape)) + graph.nodes.append(_appendTranspose(matrixA, node, perm)) + matrixA = node.inputs[0] + + # If transB is set then the matrix is of shape [N x K] and it doesn't need to be transposed, otherwise its shape is [K x N] and it has to be transposed + if node.attrs['transB'] == 0: + perm = _swapLastTwoDimsPermutation(len(matrixB.shape)) + matrixB.values = matrixB.values.transpose(perm) # Align dimensions for convolution expandAxis = [] @@ -522,11 +430,6 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): matrixAExpandDimsNode, pwIn = _appendExpandDims(matrixA, name, axis = expandAxis) graph.nodes.append(matrixAExpandDimsNode) - # If transB is set then the matrix is of shape [N x K] and it doesn't need to be transposed, otherwise its shape is [K x N] and it has to be transposed - if not 'transB' in requantizedGemm.attrs or requantizedGemm.attrs['transB'] == 0: - # matrixBTransposed, shape [N x K] - matrixBTransposeNode, matrixB = _appendTransposeNode(matrixB, name, _permutationLastTwoDims(len(matrixB.shape))) - graph.nodes.append(matrixBTransposeNode) # pwWeight, shape [N x 1 x 1 x K] matrixBExpandDimsNode, pwWeight = _appendExpandDims(matrixB, name, axis = (1, 2)) graph.nodes.append(matrixBExpandDimsNode) @@ -548,14 +451,14 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): 'kernel_shape': [1, 1], 'pads': [0, 0, 0, 0], 'strides': [1, 1], - 'div': requantizedGemm.attrs['div'], - 'n_levels_out': requantizedGemm.attrs['n_levels_out'], - 'shift': requantizedGemm.attrs['shift'], - 'signed': requantizedGemm.attrs['signed'], + 'div': node.attrs['div'], + 'n_levels_out': node.attrs['n_levels_out'], + 'shift': node.attrs['shift'], + 'signed': node.attrs['signed'], } - add = requantizedGemm.inputs[2] - mul = requantizedGemm.inputs[3] + add = node.inputs[2] + mul = node.inputs[3] _inputs = [pwIn, pwWeight, mul, add] @@ -566,9 +469,9 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): attrs = pwAttrs) graph.nodes.append(pw) - requantizedGemm.inputs.clear() - requantizedGemm.outputs.clear() - graph.nodes.remove(requantizedGemm) + node.inputs.clear() + node.outputs.clear() + graph.nodes.remove(node) return graph @@ -577,23 +480,16 @@ def _requantized_gemm_to_pw_fun(graph: gs.Graph, match: Match, name: str): class RequantizedGemmToPwPass(ReplaceSequentialPatternPass): def __init__(self): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['out'], op = 'RequantizedGemm', name = 'requantizedGemm') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern("RequantizedGemm") super().__init__(graph, _requantized_gemm_to_pw_fun, "_REQUANTIZED_GEMM_TO_PW_PASS") def _remove_global_output_reshape_fun(graph: gs.Graph, match: Match, name: str): - matched_nodes = list(match.nodes_map.values()) - reshape = matched_nodes[0] - - isGlobalOutput = len(reshape.outputs[0].outputs) == 0 + node = next(iter((match.nodes_map.values()))) + isGlobalOutput = len(node.outputs[0].outputs) == 0 if isGlobalOutput: - graph.deleteNode(reshape) + graph.deleteNode(node) return graph @@ -602,26 +498,19 @@ def _remove_global_output_reshape_fun(graph: gs.Graph, match: Match, name: str): class RemoveGlobalOutputReshapePass(ReplaceSequentialPatternPass): def __init__(self): - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['out'], op = 'Reshape', name = 'reshape') - graph.outputs.append(output) - graph.inputs.append(_input) - + graph = _singleNodePattern("Reshape") super().__init__(graph, _remove_global_output_reshape_fun, "_REMOVE_GLOBAL_OUTPUT_RESHAPE_PASS") def _remove_empty_conv_bias_fun(graph: gs.Graph, match: Match, name: str): - # Extract matched convolution - matched_nodes = list(match.nodes_map.values()) - opNode = matched_nodes[0] + node = next(iter((match.nodes_map.values()))) - # Check if the Conv node has a bias input - # If it does, check if the bias only contains zeros - if len(opNode.inputs) > 2 and np.all(opNode.inputs[2].values == 0): - del opNode.inputs[2] + # Check if the node has an all-zero bias and remove it + if len(node.inputs) == 3: + bias = node.inputs[2] + if isinstance(bias, gs.Constant) and np.all(bias.values == 0): + del node.inputs[2] - # Return updated graph return graph @@ -629,13 +518,6 @@ def _remove_empty_conv_bias_fun(graph: gs.Graph, match: Match, name: str): class RemoveEmptyConvBiasPass(ReplaceSequentialPatternPass): def __init__(self): - # Initialized graph with a Conv node - graph = gs.Graph() - _input = gs.Variable(name = 'input_1') - output = graph.layer(inputs = [_input], outputs = ['convOut'], op = 'Conv', name = 'conv') - graph.outputs.append(output) - graph.inputs.append(_input) - - # Apply function + graph = _singleNodePattern("Conv") name = "_REMOVE_EMPTY_CONV_BIAS_PASS" super().__init__(graph, _remove_empty_conv_bias_fun, name) diff --git a/Deeploy/Targets/Neureka/Deployer.py b/Deeploy/Targets/Neureka/Deployer.py index e9b966569a..be34e1f4d3 100644 --- a/Deeploy/Targets/Neureka/Deployer.py +++ b/Deeploy/Targets/Neureka/Deployer.py @@ -8,7 +8,7 @@ from Deeploy.AbstractDataTypes import Pointer from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ - NeurekaNCHWtoNHWCPass, PULPNCHWtoNHWCPass + NCHWtoNHWCPass, PULPNCHWtoNHWCPass from Deeploy.DeeployTypes import DeploymentPlatform, TopologyOptimizer from Deeploy.Targets.Neureka.TopologyOptimizationPasses.Passes import ConvEngineDiscolorationPass, \ NeurekaOptimizationPass @@ -33,7 +33,7 @@ def __init__(self, if self.Platform.engines[0].enable3x3: for idx in range(len(self.loweringOptimizer.passes)): if isinstance(self.loweringOptimizer.passes[idx], PULPNCHWtoNHWCPass): - self.loweringOptimizer.passes[idx] = NeurekaNCHWtoNHWCPass(self.default_channels_first) + self.loweringOptimizer.passes[idx] = NCHWtoNHWCPass(self.default_channels_first) self.loweringOptimizer.passes += [ ConvEngineDiscolorationPass(), From 5db6de3e93690dc5a9dd39770b339dec98dbe5f4 Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Sun, 26 Oct 2025 19:53:01 +0100 Subject: [PATCH 15/28] Remove memory-aware node bindings (#123) Remove memory-aware node bindings because it makes the great parser refactor easier. The memory-aware node bindings exist only for Neureka to be able to separate bindings that use the dedicated weight memory vs. those who don't. But those bindings can simply be rewritten to check whether the weights reside in weight memory and change behavior accordingly. By removing the memory-aware node bindings, we remove another dependency on having hoisted buffers in the middle of parsing. The RequantHelpers are a bonus that fixes the requantization mul and add hyperrectangles to keep the rank of the original tensors. ## Added - RequantHelpers.py for Neureka's TileConstraints ## Changed - Removed NodeMemoryLevelChecker, MemoryAwareNodeBinding - _parseNode from MemoryNetworkDeployer since we don't need the annotations before typeChecking anymore - Wmem variants of bindings and tile constraints from Neureka ## Fixed - Keep mul/add rank of requantized Neureka tile constraints --- CHANGELOG.md | 6 + .../NetworkDeployerWrapper.py | 7 +- Deeploy/MemoryLevelExtension/MemoryLevels.py | 62 +-- .../NetworkDeployers/MemoryLevelDeployer.py | 61 +-- Deeploy/Targets/Neureka/Bindings.py | 28 -- Deeploy/Targets/Neureka/Engine.py | 28 +- .../TileConstraints/NeurekaDenseConstraint.py | 360 +++-------------- .../NeurekaDepthwiseConstraint.py | 356 ++--------------- .../NeurekaPointwiseConstraint.py | 367 ++---------------- .../Neureka/TileConstraints/RequantHelpers.py | 53 +++ Deeploy/Targets/Neureka/Tiler.py | 26 +- 11 files changed, 214 insertions(+), 1140 deletions(-) create mode 100644 Deeploy/Targets/Neureka/TileConstraints/RequantHelpers.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 67a3684c82..357a2a39e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Remove memory-aware node bindings [#123](https://github.com/pulp-platform/Deeploy/pull/123) - Fix missing const's layout transformation and refactor NCHWtoNHWC passes [#122](https://github.com/pulp-platform/Deeploy/pull/122) - Fix aliasing [#125](https://github.com/pulp-platform/Deeploy/pull/125) - Support for 1D Autoencoder [#98](https://github.com/pulp-platform/Deeploy/pull/98) @@ -49,6 +50,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Buffer utilities: `checkNumLevels` validation and `sizeInBytes` method - Per–memory-level usage tracking and worst-case reporting in `NetworkContext` - Memory/I/O summaries and input/output logging in deployers +- RequantHelpers.py for Neureka's TileConstraints ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -80,6 +82,9 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Refactored `hoistConstant` - Refactored TransientBuffer's `__init__` - Refactor of the NCHWtoNHWC passes +- Removed NodeMemoryLevelChecker, MemoryAwareNodeBinding +- Removed _parseNode from MemoryNetworkDeployer since we don't need the annotations before typeChecking anymore +- Removed Wmem variants of bindings and tile constraints from Neureka ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon @@ -92,6 +97,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Fixed `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) - Fixed aliasing - Missing layout transformation of the const's (bias, mul, add, shift in Conv/RequantizedConv) +- Keep mul/add rank of requantized Neureka tile constraints ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py index 90ce3f99ad..f07fe57c96 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Tuple, Union +from typing import Any, Union import onnx_graphsurgeon as gs @@ -63,11 +63,6 @@ def lower(self, graph: gs.Graph) -> gs.Graph: def codeTransform(self, verbose: CodeGenVerbosity = _NoVerbosity): return self._innerObject.codeTransform(verbose) - # MemoryAwareDeployer augment - def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, - default_channels_first: bool) -> Tuple[NetworkContext, bool]: - return self._innerObject._parseNode(node, ctxt, default_channels_first) - # PULPDeployer augment def generateBufferAllocationCode(self) -> str: return self._innerObject.generateBufferAllocationCode() diff --git a/Deeploy/MemoryLevelExtension/MemoryLevels.py b/Deeploy/MemoryLevelExtension/MemoryLevels.py index 53f236c43f..5cf4abcf13 100644 --- a/Deeploy/MemoryLevelExtension/MemoryLevels.py +++ b/Deeploy/MemoryLevelExtension/MemoryLevels.py @@ -2,12 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Optional, Sequence, Tuple - -import onnx_graphsurgeon as gs - -from Deeploy.DeeployTypes import CodeTransformation, NetworkContext, NodeBinding, NodeTemplate, NodeTypeChecker, \ - OperatorRepresentation +from typing import Dict, List, Optional class MemoryLevel(): @@ -109,58 +104,3 @@ def getDefaultMemoryLevel(self): if self._defaultMemoryLevel is None: raise ValueError('defaultMemoryLevel level not set!') return self._defaultMemoryLevel - - -class NodeMemoryLevelChecker(): - - def __init__(self, inputMemoryLevels: Sequence[Optional[str]], outputMemoryLevels: Sequence[Optional[str]]): - self.inputMemoryLevels = inputMemoryLevels - self.outputMemoryLevels = outputMemoryLevels - - def _memEq(self, memoryLevel: str, annotatedMemoryLevel: str) -> bool: - if memoryLevel is None: - return True - else: - return memoryLevel == annotatedMemoryLevel - - def _checkMemoryLevels(self, ctxt: NetworkContext, memoryLevels: Sequence[str], - tensors: Sequence[gs.Tensor]) -> bool: - buffers = [ctxt.lookup(tensor.name) for tensor in tensors] - if not all(hasattr(buffer, "_memoryLevel") for buffer in buffers): - return False - - annotatedMemoryLevels = [buffer._memoryLevel for buffer in buffers] - if all( - self._memEq(memoryLevel, annotatedMemoryLevel) - for memoryLevel, annotatedMemoryLevel in zip(memoryLevels, annotatedMemoryLevels)): - return True - else: - return False - - def check(self, ctxt: NetworkContext, node: gs.Node, operatorRepresentation) -> Tuple[NetworkContext, bool]: - if self._checkMemoryLevels(ctxt, self.inputMemoryLevels, node.inputs) and self._checkMemoryLevels( - ctxt, self.outputMemoryLevels, node.outputs): - return ctxt, True - else: - return ctxt, False - - -class MemoryAwareNodeBinding(NodeBinding): - - def __init__(self, typeChecker: NodeTypeChecker, memoryLevelChecker: NodeMemoryLevelChecker, template: NodeTemplate, - codeTransformer: CodeTransformation): - super().__init__(typeChecker, template, codeTransformer) - self.memoryLevelChecker = memoryLevelChecker - - def typeCheck(self, ctxt: NetworkContext, node: gs.Node, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, bool]: - newCtxt, ret = self.memoryLevelChecker.check(ctxt, node, operatorRepresentation) - if ret: - return super().typeCheck(newCtxt, node, operatorRepresentation) - - return ctxt, False - - -def memoryAwareNodeBindingExtension(binding: NodeBinding, - memoryLevelChecker: NodeMemoryLevelChecker) -> MemoryAwareNodeBinding: - return MemoryAwareNodeBinding(binding.typeChecker, memoryLevelChecker, binding.template, binding.codeTransformer) diff --git a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py index 46aa144135..2599f9e819 100644 --- a/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py +++ b/Deeploy/MemoryLevelExtension/NetworkDeployers/MemoryLevelDeployer.py @@ -11,7 +11,7 @@ from Deeploy.CommonExtensions.NetworkDeployers.NetworkDeployerWrapper import NetworkDeployerWrapper from Deeploy.CommonExtensions.NetworkDeployers.SignPropDeployer import SignPropDeployer from Deeploy.DeeployTypes import CodeGenVerbosity, ConstantBuffer, DeploymentEngine, DeploymentPlatform, \ - NetworkContext, NetworkDeployer, NetworkOptimizationPass, NetworkOptimizer, ONNXLayer, Schedule, StructBuffer, \ + NetworkContext, NetworkDeployer, NetworkOptimizationPass, NetworkOptimizer, Schedule, StructBuffer, \ TopologyOptimizer, TransientBuffer, VariableBuffer, _NoVerbosity from Deeploy.Logging import DEFAULT_LOGGER as log from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel @@ -128,25 +128,16 @@ def getTargetMemoryLevelMapping(self) -> TargetMemoryLevelMapping: f"Platform should be a MemoryPlatform or MemoryPlatformWrapper! Got {type(self.Platform).__name__}" return TargetMemoryLevelMapping(self.graph, self.Platform, self.ctxt) - def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, - default_channels_first: bool) -> Tuple[NetworkContext, bool]: - - newCtxt, parsePass = super()._parseNode(node, ctxt, default_channels_first) - - if not parsePass: - return ctxt, False - - newCtxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(newCtxt, self.graph) - - return newCtxt, parsePass - def bind(self): + log.info("- Perform Memory Level Annotation") + # LMACAN: Annotate before bind because during binding (specifically alignToContext) templates + # may expect the memoryLevel annotation already. + self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) ret = super().bind() if not ret: return False - log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) @@ -181,29 +172,16 @@ def getTargetMemoryLevelMapping(self) -> TargetMemoryLevelMapping: f"Platform should be a MemoryPlatform or MemoryPlatformWrapper! Got {type(self.Platform).__name__}" return TargetMemoryLevelMapping(self.graph, self.Platform, self.ctxt) - def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, - default_channels_first: bool) -> Tuple[NetworkContext, bool]: - - newCtxt, parsePass = node.parse(ctxt.copy(), default_channels_first) - - if not parsePass: - return ctxt, False - - newCtxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(newCtxt, self.graph) - newCtxt, LayerBindSuccess = node.typeCheck(newCtxt) - - if not LayerBindSuccess: - return ctxt, False - - return newCtxt, True - def bind(self): + log.info("- Perform Memory Level Annotation") + # LMACAN: Annotate before bind because during binding (specifically alignToContext) templates + # may expect the memoryLevel annotation already. + self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) ret = super().bind() if not ret: return False - log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) @@ -229,29 +207,16 @@ def getTargetMemoryLevelMapping(self) -> TargetMemoryLevelMapping: f"Platform should be a MemoryPlatform or MemoryPlatformWrapper! Got {type(self.Platform).__name__}" return TargetMemoryLevelMapping(self.graph, self.Platform, self.ctxt) - def _parseNode(self, node: ONNXLayer, ctxt: NetworkContext, - default_channels_first: bool) -> Tuple[NetworkContext, bool]: - - newCtxt, parsePass = node.parse(ctxt.copy(), default_channels_first) - - if not parsePass: - return ctxt, False - - newCtxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(newCtxt, self.graph) - newCtxt, LayerBindSuccess = node.typeCheck(newCtxt) - - if not LayerBindSuccess: - return ctxt, False - - return newCtxt, True - def bind(self): + log.info("- Perform Memory Level Annotation") + # LMACAN: Annotate before bind because during binding (specifically alignToContext) templates + # may expect the memoryLevel annotation already. + self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) ret = super().bind() if not ret: return False - log.info("- Perform Memory Level Annotation") # SCHEREMO: There might be hoisting; reassign memoryLevel preferences self.ctxt, self.graph = self.memoryLevelAnnotationOptimizer.optimize(self.ctxt, self.graph) diff --git a/Deeploy/Targets/Neureka/Bindings.py b/Deeploy/Targets/Neureka/Bindings.py index 010d29db01..4e73df784f 100644 --- a/Deeploy/Targets/Neureka/Bindings.py +++ b/Deeploy/Targets/Neureka/Bindings.py @@ -5,7 +5,6 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import int8_t, int32_t, uint8_t from Deeploy.DeeployTypes import NodeBinding -from Deeploy.MemoryLevelExtension.MemoryLevels import NodeMemoryLevelChecker, memoryAwareNodeBindingExtension from Deeploy.Targets.Generic.TypeCheckers import ConvChecker from Deeploy.Targets.Neureka.Templates.ConvTemplate import NeurekaDenseConv2D_Template, NeurekaDWConv2D_Template, \ NeurekaPWConv2D_Template, NeurekaRqntDenseConv2D_Template, NeurekaRqntDWConv2D_Template, \ @@ -33,15 +32,6 @@ for weight_type in [uint8_t, int8_t] ] -NeurekaWmemRQSPWConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM", None, None], [None])) - for binding in NeurekaRQSPWConv2DBindings -] -NeurekaWmemPWConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM"], [None])) - for binding in NeurekaPWConv2DBindings -] - NeurekaRQSDWConv2DBindings = [ NodeBinding( PULPConvChecker( @@ -62,15 +52,6 @@ for weight_type in [uint8_t, int8_t] ] -NeurekaWmemRQSDWConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM", None, None], [None])) - for binding in NeurekaRQSDWConv2DBindings -] -NeurekaWmemDWConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM"], [None])) - for binding in NeurekaDWConv2DBindings -] - NeurekaRQSDenseConv2DBindings = [ NodeBinding( PULPConvChecker( @@ -91,12 +72,3 @@ for data_in_type in [uint8_t, int8_t] for weight_type in [uint8_t, int8_t] ] - -NeurekaWmemRQSDenseConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM", None, None], [None])) - for binding in NeurekaRQSDenseConv2DBindings -] -NeurekaWmemDenseConv2DBindings = [ - memoryAwareNodeBindingExtension(binding, NodeMemoryLevelChecker([None, "WeightMemory_SRAM"], [None])) - for binding in NeurekaDenseConv2DBindings -] diff --git a/Deeploy/Targets/Neureka/Engine.py b/Deeploy/Targets/Neureka/Engine.py index 5d52840f62..2585b1a688 100644 --- a/Deeploy/Targets/Neureka/Engine.py +++ b/Deeploy/Targets/Neureka/Engine.py @@ -12,27 +12,17 @@ NeurekaRQSDenseConv2DParser, NeurekaRQSDWConv2DParser, NeurekaRQSPWConv2DParser from Deeploy.Targets.Neureka.Tiler import NeurekaDenseConv2DTilingReadyBindings, NeurekaDWConv2DTilingReadyBindings, \ NeurekaPWConv2DTilingReadyBindings, NeurekaRQSDenseConv2DTilingReadyBindings, \ - NeurekaRQSDWConv2DTilingReadyBindings, NeurekaRQSPWConv2DTilingReadyBindings, \ - NeurekaWmemDenseConv2DTilingReadyBindings, NeurekaWmemDWConv2DTilingReadyBindings, \ - NeurekaWmemPWConv2DTilingReadyBindings, NeurekaWmemRQSDenseConv2DTilingReadyBindings, \ - NeurekaWmemRQSDWConv2DTilingReadyBindings, NeurekaWmemRQSPWConv2DTilingReadyBindings + NeurekaRQSDWConv2DTilingReadyBindings, NeurekaRQSPWConv2DTilingReadyBindings from Deeploy.Targets.PULPOpen.Layers import PULPRQSConvLayer -NeurekaRqntPWConv2DMapper = NodeMapper( - NeurekaRQSPWConv2DParser(), NeurekaWmemRQSPWConv2DTilingReadyBindings + NeurekaRQSPWConv2DTilingReadyBindings) -NeurekaPWConv2DMapper = NodeMapper(NeurekaPWConv2DParser(), - NeurekaWmemPWConv2DTilingReadyBindings + NeurekaPWConv2DTilingReadyBindings) - -NeurekaRqntDWConv2DMapper = NodeMapper( - NeurekaRQSDWConv2DParser(), NeurekaWmemRQSDWConv2DTilingReadyBindings + NeurekaRQSDWConv2DTilingReadyBindings) -NeurekaDWConv2DMapper = NodeMapper(NeurekaDWConv2DParser(), - NeurekaWmemDWConv2DTilingReadyBindings + NeurekaDWConv2DTilingReadyBindings) - -NeurekaRqntDenseConv2DMapper = NodeMapper( - NeurekaRQSDenseConv2DParser(), - NeurekaWmemRQSDenseConv2DTilingReadyBindings + NeurekaRQSDenseConv2DTilingReadyBindings) -NeurekaDenseConv2DMapper = NodeMapper(NeurekaDenseConv2DParser(), - NeurekaWmemDenseConv2DTilingReadyBindings + NeurekaDenseConv2DTilingReadyBindings) +NeurekaRqntPWConv2DMapper = NodeMapper(NeurekaRQSPWConv2DParser(), NeurekaRQSPWConv2DTilingReadyBindings) +NeurekaPWConv2DMapper = NodeMapper(NeurekaPWConv2DParser(), NeurekaPWConv2DTilingReadyBindings) + +NeurekaRqntDWConv2DMapper = NodeMapper(NeurekaRQSDWConv2DParser(), NeurekaRQSDWConv2DTilingReadyBindings) +NeurekaDWConv2DMapper = NodeMapper(NeurekaDWConv2DParser(), NeurekaDWConv2DTilingReadyBindings) + +NeurekaRqntDenseConv2DMapper = NodeMapper(NeurekaRQSDenseConv2DParser(), NeurekaRQSDenseConv2DTilingReadyBindings) +NeurekaDenseConv2DMapper = NodeMapper(NeurekaDenseConv2DParser(), NeurekaDenseConv2DTilingReadyBindings) NeurekaMapping = { 'RequantizedConv': diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py index a5cacf298c..814024a877 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDenseConstraint.py @@ -6,9 +6,10 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import uint8_t, uint16_t, uint32_t -from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation +from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation, VariableBuffer from Deeploy.Targets.Neureka.Templates.ConvTemplate import Neureka2DDenseConvTemplate, getInputAddrOffset, \ ioStridesFromDimensions +from Deeploy.Targets.Neureka.TileConstraints.RequantHelpers import requantAddGeometricalConstraint, requantLoadSchedule from Deeploy.Targets.PULPOpen.TileConstraints.ConvTileConstraint import Conv2DTileConstraint from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TileConstraint import TileConstraint @@ -21,7 +22,6 @@ class NeurekaDenseConv2DTileConstraint(TileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - # Get to-be-tiled tensor's buffers inputBufferName = parseDict['data_in'] weightBufferName = parseDict['weight'] outputBufferName = parseDict['data_out'] @@ -30,7 +30,6 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw padding = parseDict["pads"] dilation = parseDict["dilations"] - # Add I/O dimensions to the model as variables for bufferName in [inputBufferName, weightBufferName, outputBufferName]: tilerModel.addTensorDimToModel(ctxt, bufferName) @@ -48,9 +47,15 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 2) outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) + # Map output dims to inputs dims - tilerModel.addConstraint(outputBatchVar == inputBatchVar) # Batch - tilerModel.addConstraint(outputChannelVar == weightOutChannelVar) # Output Channel + tilerModel.addConstraint(outputBatchVar == inputBatchVar) + + weightBuffer = ctxt.lookup(weightBufferName) + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + tilerModel.addConstraint(weightOutChannelVar == weightOutChannelVar.Max()) + else: + tilerModel.addConstraint(weightOutChannelVar == outputChannelVar) inputBuffer = ctxt.lookup(inputBufferName) @@ -64,22 +69,11 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw @staticmethod def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - # Get to-be-tiled tensor's buffers - inputBuffer = ctxt.lookup(name = parseDict['data_in']) - weightBuffer = ctxt.lookup(name = parseDict['weight']) - outputBuffer = ctxt.lookup(name = parseDict['data_out']) - - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 3) - - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 3) + inputHeightVar = tilerModel.getTensorDimVar(tensorName = parseDict['data_in'], dimIdx = 1) + inputWidthVar = tilerModel.getTensorDimVar(tensorName = parseDict['data_in'], dimIdx = 2) + inputChannelVar = tilerModel.getTensorDimVar(tensorName = parseDict['data_in'], dimIdx = 3) strides = parseDict["strides"] - padding = parseDict["pads"] tilerModel.addConstraint((inputHeightVar % strides[0]) == 0) tilerModel.addConstraint((inputWidthVar % strides[1]) == 0) @@ -101,7 +95,7 @@ def serializeTilingSolution( operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - addrNames = ['data_in', 'weight', 'data_out'] + addrNames = ['data_in', 'data_out'] inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) @@ -109,7 +103,6 @@ def serializeTilingSolution( varOut = operatorRepresentation['data_out'] inputInCubes = [] - inputWeightCubes = [] replacements: Dict[str, List[int]] = { "padding_y_top": [], "padding_y_bottom": [], @@ -161,272 +154,15 @@ def serializeTilingSolution( pads = operatorRepresentation['pads'] strides = operatorRepresentation['strides'] - for cube in outputCubes: - (BatchOffset, HOffset, WOffset, COffset) = cube.offset - (BatchSize, HSize, WSize, CSize) = cube.dims - - InCube, padding_tuple = Conv2DTileConstraint.computeInputCube((weightH, weightW), pads, strides, weightC, - cube, - ctxt.lookup(varOut).shape) - padding_left, padding_right, padding_top, padding_bottom = padding_tuple - - replacements['padding_y_top'].append(padding_top) - replacements['padding_y_bottom'].append(padding_bottom) - replacements['padding_x_left'].append(padding_left) - replacements['padding_x_right'].append(padding_right) - - inBSize, inHSize, inWSize, inCSize = InCube.dims - - dim_im_in_x_stride, dim_im_in_y_stride = ioStridesFromDimensions(inWSize, inCSize, - operatorRepresentation["input_bits"]) - replacements['dim_im_in_x_stride'].append(dim_im_in_x_stride) - replacements['dim_im_in_y_stride'].append(dim_im_in_y_stride) - dim_im_out_x_stride, dim_im_out_y_stride = ioStridesFromDimensions(WSize, CSize, - operatorRepresentation["output_bits"]) - replacements['dim_im_out_x_stride'].append(dim_im_out_x_stride) - replacements['dim_im_out_y_stride'].append(dim_im_out_y_stride) - - replacements['input_addr_offset'].append( - getInputAddrOffset(inWSize, dim_im_in_y_stride, padding_top, padding_left)) - - nKo, nKi, nHo, nWo, bKo, bKi, bHo, bWo, bHi, bWi = Neureka2DDenseConvTemplate.getCounters( - inCSize, HSize, WSize, CSize, padding_bottom, padding_right, operatorRepresentation) - - replacements["nKo"].append(nKo) - replacements["nKi"].append(nKi) - replacements["nHo"].append(nHo) - replacements["nWo"].append(nWo) - replacements["bKo"].append(bKo) - replacements["bKi"].append(bKi) - replacements["bHo"].append(bHo) - replacements["bWo"].append(bWo) - replacements["bHi"].append(bHi) - replacements["bWi"].append(bWi) - - inputInCubes.append(InCube) - - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - - inputWeightCubes.append(WeightCube) - - inputLoadSchedule = [] - outputLoadSchedule = [] - - for a, b in zip(inputInCubes, inputWeightCubes): - inputLoadSchedule.append({"data_in": a, "weight": b}) - - for out in outputCubes: - outputLoadSchedule.append({"data_out": out}) - - tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) - variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) + outputBuffer = ctxt.lookup(varOut) + assert isinstance(outputBuffer, VariableBuffer) - return variableReplacementSchedule, tilingSchedule - - -class NeurekaRQSDenseConv2DTileConstraint(NeurekaDenseConv2DTileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaDenseConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( - tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['mul', 'add'] - inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, - addrNames) - newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - - inputRequantCubes = [] for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) - newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] - - newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, - tilingSchedule.outputLoadSchedule) - - return variableReplacementSchedule, newTilingSchedule - - -class NeurekaWmemDenseConv2DTileConstraint(TileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - inputBufferName = parseDict['data_in'] - weightBufferName = parseDict['weight'] - outputBufferName = parseDict['data_out'] - - strides = parseDict["strides"] - padding = parseDict["pads"] - dilation = parseDict["dilations"] - - for bufferName in [inputBufferName, weightBufferName, outputBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 0) - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 3) - - outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 0) - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - - # Map output dims to inputs dims - tilerModel.addConstraint(outputBatchVar == inputBatchVar) - - tilerModel.addConstraint(inputHeightVar >= 3) - tilerModel.addConstraint(inputWidthVar >= 3) - - inputBuffer = ctxt.lookup(inputBufferName) - - effectiveHeight = inputHeightVar + ((padding[0] + padding[2]) * (inputHeightVar == inputBuffer.shape[1])) - effectiveWidth = inputWidthVar + ((padding[1] + padding[3]) * (inputWidthVar == inputBuffer.shape[2])) - - tilerModel.addConstraint((outputHeightVar == (effectiveHeight - (3 - 1) - 1) // strides[0] + 1)) - tilerModel.addConstraint((outputWidthVar == (effectiveWidth - (3 - 1) - 1) // strides[1] + 1)) - - return tilerModel - - @staticmethod - def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - # Get to-be-tiled tensor's buffers - inputBuffer = ctxt.lookup(name = parseDict['data_in']) - weightBuffer = ctxt.lookup(name = parseDict['weight']) - outputBuffer = ctxt.lookup(name = parseDict['data_out']) - - inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 0) - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 3) - - outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 0) - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 3) - - strides = parseDict["strides"] - padding = parseDict["pads"] - - tilerModel.addConstraint((inputHeightVar % strides[0]) == 0) - tilerModel.addConstraint((inputWidthVar % strides[1]) == 0) - - tilerModel.addConstraint(inputChannelVar == inputChannelVar.Max()) - - tilerModel.addConstraint(inputHeightVar == inputHeightVar.Max(), strategy = PerformanceHint(1)) - tilerModel.addConstraint(inputWidthVar == inputWidthVar.Max(), strategy = PerformanceHint(1)) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['data_in', 'data_out'] - inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, - operatorRepresentation, addrNames) - - varWeight = operatorRepresentation['weight'] - varOut = operatorRepresentation['data_out'] - - inputInCubes = [] - replacements: Dict[str, List[int]] = { - "padding_y_top": [], - "padding_y_bottom": [], - "padding_x_left": [], - "padding_x_right": [], - "weight_addr_offset": [], - "dim_im_in_x_stride": [], - "dim_im_in_y_stride": [], - "dim_im_out_x_stride": [], - "dim_im_out_y_stride": [], - "input_addr_offset": [], - "nKo": [], - "nKi": [], - "nHo": [], - "nWo": [], - "bKo": [], - "bKi": [], - "bHo": [], - "bWo": [], - "bHi": [], - "bWi": [], - } - - replacementTypes = { - "padding_y_top": PointerClass(uint8_t), - "padding_y_bottom": PointerClass(uint8_t), - "padding_x_left": PointerClass(uint8_t), - "padding_x_right": PointerClass(uint8_t), - "weight_addr_offset": PointerClass(uint32_t), - "dim_im_in_x_stride": PointerClass(uint32_t), - "dim_im_in_y_stride": PointerClass(uint32_t), - "dim_im_out_x_stride": PointerClass(uint32_t), - "dim_im_out_y_stride": PointerClass(uint32_t), - "input_addr_offset": PointerClass(uint32_t), - "nKo": PointerClass(uint16_t), - "nKi": PointerClass(uint16_t), - "nHo": PointerClass(uint16_t), - "nWo": PointerClass(uint16_t), - "bKo": PointerClass(uint16_t), - "bKi": PointerClass(uint16_t), - "bHo": PointerClass(uint16_t), - "bWo": PointerClass(uint16_t), - "bHi": PointerClass(uint16_t), - "bWi": PointerClass(uint16_t), - } - - weightH = operatorRepresentation['dim_kernel_y'] - weightW = operatorRepresentation['dim_kernel_x'] - weightC = operatorRepresentation['ch_im_in'] - - pads = operatorRepresentation['pads'] - strides = operatorRepresentation['strides'] - - for absoluteCube in absoluteOutputCubes: - cube = absoluteCube.rectangle (BatchOffset, HOffset, WOffset, COffset) = cube.offset (BatchSize, HSize, WSize, CSize) = cube.dims InCube, padding_tuple = Conv2DTileConstraint.computeInputCube((weightH, weightW), pads, strides, weightC, - cube, - ctxt.lookup(varOut).shape) + cube, outputBuffer.shape) padding_left, padding_right, padding_top, padding_bottom = padding_tuple replacements['padding_y_top'].append(padding_top) @@ -464,11 +200,6 @@ def serializeTilingSolution( inputInCubes.append(InCube) - _, _, _, absoluteCOffset = absoluteCube.absoluteOffset - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) - inputLoadSchedule = [] outputLoadSchedule = [] @@ -478,34 +209,39 @@ def serializeTilingSolution( for out in outputCubes: outputLoadSchedule.append({"data_out": out}) + weightBuffer = ctxt.lookup(varWeight) + assert isinstance(weightBuffer, VariableBuffer) + weightShape = weightBuffer.shape + + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + replacements['weight_addr_offset'] = [] + replacementTypes['weight_addr_offset'] = PointerClass(uint32_t) + for absoluteCube in absoluteOutputCubes: + COffset, CSize = absoluteCube.absoluteOffset[-1], absoluteCube.rectangle.dims[-1] + WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, weightBuffer)) + else: + inputWeightBaseOffsets, outputWeightBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, + operatorRepresentation, ['weight']) + inputBaseOffsets.update(inputWeightBaseOffsets) + outputBaseOffsets.update(outputWeightBaseOffsets) + + for cube, load in zip(outputCubes, inputLoadSchedule): + COffset, CSize = cube.offset[-1], cube.dims[-1] + load['weight'] = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) return variableReplacementSchedule, tilingSchedule -class NeurekaWmemRQSDenseConv2DTileConstraint(NeurekaWmemDenseConv2DTileConstraint): +class NeurekaRQSDenseConv2DTileConstraint(NeurekaDenseConv2DTileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaWmemDenseConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel + tilerModel = NeurekaDenseConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) + return requantAddGeometricalConstraint(tilerModel, parseDict, ctxt) @classmethod def serializeTilingSolution( @@ -515,22 +251,16 @@ def serializeTilingSolution( variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - addrNames = ['mul', 'add'] inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - inputRequantCubes = [] - for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) + requantSchedule = requantLoadSchedule(absoluteOutputCubes, ctxt, operatorRepresentation) newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] + **load, + **rqLoad + } for load, rqLoad in zip(tilingSchedule.inputLoadSchedule, requantSchedule)] newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, tilingSchedule.outputLoadSchedule) diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py index d0e32597cc..fd5d791119 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaDepthwiseConstraint.py @@ -6,9 +6,10 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import uint8_t, uint16_t, uint32_t -from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation +from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation, VariableBuffer from Deeploy.Targets.Neureka.Templates.ConvTemplate import Neureka2DDWConvTemplate, getInputAddrOffset, \ ioStridesFromDimensions +from Deeploy.Targets.Neureka.TileConstraints.RequantHelpers import requantAddGeometricalConstraint, requantLoadSchedule from Deeploy.Targets.PULPOpen.TileConstraints.ConvTileConstraint import Conv2DTileConstraint from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TileConstraint import TileConstraint @@ -21,7 +22,6 @@ class NeurekaDWConv2DTileConstraint(TileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - # Get to-be-tiled tensor's buffers inputBufferName = parseDict['data_in'] weightBufferName = parseDict['weight'] outputBufferName = parseDict['data_out'] @@ -30,7 +30,6 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw padding = parseDict["pads"] dilation = parseDict["dilations"] - # Add I/O dimensions to the model as variables for bufferName in [inputBufferName, weightBufferName, outputBufferName]: tilerModel.addTensorDimToModel(ctxt, bufferName) @@ -40,263 +39,6 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 3) weightOutChannelVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 0) - weightInChannelMajorVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 1) - weightBitsVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 2) - weightBandwidthVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 3) - - outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 0) - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - # Map output dims to inputs dims - tilerModel.addConstraint(outputBatchVar == inputBatchVar) # Batch - tilerModel.addConstraint(outputChannelVar == weightOutChannelVar) # Output Channel - tilerModel.addConstraint(outputChannelVar == inputChannelVar) # Output Channel - - tilerModel.addConstraint(inputHeightVar >= 3) - tilerModel.addConstraint(inputWidthVar >= 3) - - inputBuffer = ctxt.lookup(inputBufferName) - - effectiveHeight = inputHeightVar + ((padding[0] + padding[2]) * (inputHeightVar == inputBuffer.shape[1])) - effectiveWidth = inputWidthVar + ((padding[1] + padding[3]) * (inputWidthVar == inputBuffer.shape[2])) - - tilerModel.addConstraint((outputHeightVar == (effectiveHeight - (3 - 1) - 1) // strides[0] + 1)) - tilerModel.addConstraint((outputWidthVar == (effectiveWidth - (3 - 1) - 1) // strides[1] + 1)) - - return tilerModel - - @staticmethod - def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - # Get to-be-tiled tensor's buffers - inputBuffer = ctxt.lookup(name = parseDict['data_in']) - weightBuffer = ctxt.lookup(name = parseDict['weight']) - outputBuffer = ctxt.lookup(name = parseDict['data_out']) - - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 3) - - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 3) - - strides = parseDict["strides"] - padding = parseDict["pads"] - - tilerModel.addConstraint((inputHeightVar % strides[0]) == 0) - tilerModel.addConstraint((inputWidthVar % strides[1]) == 0) - - tilerModel.addConstraint(inputHeightVar == inputHeightVar.Max(), strategy = PerformanceHint(1)) - tilerModel.addConstraint(inputWidthVar == inputWidthVar.Max(), strategy = PerformanceHint(1)) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['data_in', 'weight', 'data_out'] - inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, - operatorRepresentation, addrNames) - - varWeight = operatorRepresentation['weight'] - varOut = operatorRepresentation['data_out'] - - inputInCubes = [] - inputWeightCubes = [] - replacements: Dict[str, List[int]] = { - "padding_y_top": [], - "padding_y_bottom": [], - "padding_x_left": [], - "padding_x_right": [], - "dim_im_in_x_stride": [], - "dim_im_in_y_stride": [], - "dim_im_out_x_stride": [], - "dim_im_out_y_stride": [], - "input_addr_offset": [], - "nKo": [], - "nKi": [], - "nHo": [], - "nWo": [], - "bKo": [], - "bKi": [], - "bHo": [], - "bWo": [], - "bHi": [], - "bWi": [], - } - - replacementTypes = { - "padding_y_top": PointerClass(uint8_t), - "padding_y_bottom": PointerClass(uint8_t), - "padding_x_left": PointerClass(uint8_t), - "padding_x_right": PointerClass(uint8_t), - "dim_im_in_x_stride": PointerClass(uint32_t), - "dim_im_in_y_stride": PointerClass(uint32_t), - "dim_im_out_x_stride": PointerClass(uint32_t), - "dim_im_out_y_stride": PointerClass(uint32_t), - "input_addr_offset": PointerClass(uint32_t), - "nKo": PointerClass(uint16_t), - "nKi": PointerClass(uint16_t), - "nHo": PointerClass(uint16_t), - "nWo": PointerClass(uint16_t), - "bKo": PointerClass(uint16_t), - "bKi": PointerClass(uint16_t), - "bHo": PointerClass(uint16_t), - "bWo": PointerClass(uint16_t), - "bHi": PointerClass(uint16_t), - "bWi": PointerClass(uint16_t), - } - - weightH = operatorRepresentation['dim_kernel_y'] - weightW = operatorRepresentation['dim_kernel_x'] - weightC = operatorRepresentation['ch_im_in'] - - pads = operatorRepresentation['pads'] - strides = operatorRepresentation['strides'] - - for cube in outputCubes: - (BatchOffset, HOffset, WOffset, COffset) = cube.offset - (BatchSize, HSize, WSize, CSize) = cube.dims - - InCube, padding_tuple = Conv2DTileConstraint.computeInputCube((weightH, weightW), pads, strides, weightC, - cube, - ctxt.lookup(varOut).shape) - padding_left, padding_right, padding_top, padding_bottom = padding_tuple - - replacements['padding_y_top'].append(padding_top) - replacements['padding_y_bottom'].append(padding_bottom) - replacements['padding_x_left'].append(padding_left) - replacements['padding_x_right'].append(padding_right) - - inBSize, inHSize, inWSize, inCSize = InCube.dims - - dim_im_in_x_stride, dim_im_in_y_stride = ioStridesFromDimensions(inWSize, inCSize, - operatorRepresentation["input_bits"]) - replacements['dim_im_in_x_stride'].append(dim_im_in_x_stride) - replacements['dim_im_in_y_stride'].append(dim_im_in_y_stride) - dim_im_out_x_stride, dim_im_out_y_stride = ioStridesFromDimensions(WSize, CSize, - operatorRepresentation["output_bits"]) - replacements['dim_im_out_x_stride'].append(dim_im_out_x_stride) - replacements['dim_im_out_y_stride'].append(dim_im_out_y_stride) - - replacements['input_addr_offset'].append( - getInputAddrOffset(inWSize, dim_im_in_y_stride, padding_top, padding_left)) - - nKo, nKi, nHo, nWo, bKo, bKi, bHo, bWo, bHi, bWi = Neureka2DDWConvTemplate.getCounters( - inCSize, HSize, WSize, CSize, padding_bottom, padding_right, operatorRepresentation) - - replacements["nKo"].append(nKo) - replacements["nKi"].append(nKi) - replacements["nHo"].append(nHo) - replacements["nWo"].append(nWo) - replacements["bKo"].append(bKo) - replacements["bKi"].append(bKi) - replacements["bHo"].append(bHo) - replacements["bWo"].append(bWo) - replacements["bHi"].append(bHi) - replacements["bWi"].append(bWi) - - inputInCubes.append(InCube) - - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - - inputWeightCubes.append(WeightCube) - - inputLoadSchedule = [] - outputLoadSchedule = [] - - for a, b in zip(inputInCubes, inputWeightCubes): - inputLoadSchedule.append({"data_in": a, "weight": b}) - - for out in outputCubes: - outputLoadSchedule.append({"data_out": out}) - - tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) - variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) - - return variableReplacementSchedule, tilingSchedule - - -class NeurekaRQSDWConv2DTileConstraint(NeurekaDWConv2DTileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaDWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( - tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['mul', 'add'] - inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, - addrNames) - newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - - inputRequantCubes = [] - for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) - newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] - - newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, - tilingSchedule.outputLoadSchedule) - - return variableReplacementSchedule, newTilingSchedule - - -class NeurekaWmemDWConv2DTileConstraint(TileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - inputBufferName = parseDict['data_in'] - weightBufferName = parseDict['weight'] - outputBufferName = parseDict['data_out'] - - strides = parseDict["strides"] - padding = parseDict["pads"] - dilation = parseDict["dilations"] - - for bufferName in [inputBufferName, weightBufferName, outputBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 0) - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 3) outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 0) outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) @@ -307,6 +49,12 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw tilerModel.addConstraint(outputBatchVar == inputBatchVar) tilerModel.addConstraint(outputChannelVar == inputChannelVar) + weightBuffer = ctxt.lookup(weightBufferName) + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + tilerModel.addConstraint(weightOutChannelVar == weightOutChannelVar.Max()) + else: + tilerModel.addConstraint(weightOutChannelVar == outputChannelVar) + tilerModel.addConstraint(inputHeightVar >= 3) tilerModel.addConstraint(inputWidthVar >= 3) @@ -322,24 +70,10 @@ def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: Netw @staticmethod def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - # Get to-be-tiled tensor's buffers - inputBuffer = ctxt.lookup(name = parseDict['data_in']) - weightBuffer = ctxt.lookup(name = parseDict['weight']) - outputBuffer = ctxt.lookup(name = parseDict['data_out']) - - inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 0) - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 3) - - outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 0) - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 3) + inputHeightVar = tilerModel.getTensorDimVar(tensorName = parseDict['data_in'], dimIdx = 1) + inputWidthVar = tilerModel.getTensorDimVar(tensorName = parseDict['data_in'], dimIdx = 2) strides = parseDict["strides"] - padding = parseDict["pads"] tilerModel.addConstraint((inputHeightVar % strides[0]) == 0) tilerModel.addConstraint((inputWidthVar % strides[1]) == 0) @@ -369,7 +103,6 @@ def serializeTilingSolution( "padding_y_bottom": [], "padding_x_left": [], "padding_x_right": [], - "weight_addr_offset": [], "dim_im_in_x_stride": [], "dim_im_in_y_stride": [], "dim_im_out_x_stride": [], @@ -392,7 +125,6 @@ def serializeTilingSolution( "padding_y_bottom": PointerClass(uint8_t), "padding_x_left": PointerClass(uint8_t), "padding_x_right": PointerClass(uint8_t), - "weight_addr_offset": PointerClass(uint32_t), "dim_im_in_x_stride": PointerClass(uint32_t), "dim_im_in_y_stride": PointerClass(uint32_t), "dim_im_out_x_stride": PointerClass(uint32_t), @@ -417,8 +149,10 @@ def serializeTilingSolution( pads = operatorRepresentation['pads'] strides = operatorRepresentation['strides'] - for absoluteCube in absoluteOutputCubes: - cube = absoluteCube.rectangle + outputBuffer = ctxt.lookup(varOut) + assert isinstance(outputBuffer, VariableBuffer) + + for cube in outputCubes: (BatchOffset, HOffset, WOffset, COffset) = cube.offset (BatchSize, HSize, WSize, CSize) = cube.dims @@ -462,11 +196,6 @@ def serializeTilingSolution( inputInCubes.append(InCube) - _, _, _, absoluteCOffset = absoluteCube.absoluteOffset - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) - inputLoadSchedule = [] outputLoadSchedule = [] @@ -476,34 +205,39 @@ def serializeTilingSolution( for out in outputCubes: outputLoadSchedule.append({"data_out": out}) + weightBuffer = ctxt.lookup(varWeight) + assert isinstance(weightBuffer, VariableBuffer) + weightShape = weightBuffer.shape + + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + replacements['weight_addr_offset'] = [] + replacementTypes['weight_addr_offset'] = PointerClass(uint32_t) + for absoluteCube in absoluteOutputCubes: + COffset, CSize = absoluteCube.absoluteOffset[-1], absoluteCube.rectangle.dims[-1] + WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, weightBuffer)) + else: + inputWeightBaseOffsets, outputWeightBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, + operatorRepresentation, ['weight']) + inputBaseOffsets.update(inputWeightBaseOffsets) + outputBaseOffsets.update(outputWeightBaseOffsets) + + for cube, load in zip(outputCubes, inputLoadSchedule): + COffset, CSize = cube.offset[-1], cube.dims[-1] + load['weight'] = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) return variableReplacementSchedule, tilingSchedule -class NeurekaWmemRQSDWConv2DTileConstraint(NeurekaWmemDWConv2DTileConstraint): +class NeurekaRQSDWConv2DTileConstraint(NeurekaDWConv2DTileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaWmemDWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel + tilerModel = NeurekaDWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) + return requantAddGeometricalConstraint(tilerModel, parseDict, ctxt) @classmethod def serializeTilingSolution( @@ -513,22 +247,16 @@ def serializeTilingSolution( variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - addrNames = ['mul', 'add'] inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - inputRequantCubes = [] - for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) + requantSchedule = requantLoadSchedule(absoluteOutputCubes, ctxt, operatorRepresentation) newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] + **load, + **rqLoad + } for load, rqLoad in zip(tilingSchedule.inputLoadSchedule, requantSchedule)] newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, tilingSchedule.outputLoadSchedule) diff --git a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py index a780214e16..61a5b8756a 100644 --- a/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py +++ b/Deeploy/Targets/Neureka/TileConstraints/NeurekaPointwiseConstraint.py @@ -6,9 +6,10 @@ from Deeploy.AbstractDataTypes import PointerClass from Deeploy.CommonExtensions.DataTypes import uint8_t, uint16_t, uint32_t -from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation +from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation, VariableBuffer from Deeploy.Targets.Neureka.Templates.ConvTemplate import Neureka2DPWConvTemplate, getInputAddrOffset, \ ioStridesFromDimensions +from Deeploy.Targets.Neureka.TileConstraints.RequantHelpers import requantAddGeometricalConstraint, requantLoadSchedule from Deeploy.Targets.PULPOpen.TileConstraints.ConvTileConstraint import Conv2DTileConstraint from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TileConstraint import TileConstraint @@ -21,315 +22,34 @@ class NeurekaPWConv2DTileConstraint(TileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - # Get to-be-tiled tensor's buffers inputBufferName = parseDict['data_in'] weightBufferName = parseDict['weight'] outputBufferName = parseDict['data_out'] - # Add I/O dimensions to the model as variables for bufferName in [inputBufferName, weightBufferName, outputBufferName]: tilerModel.addTensorDimToModel(ctxt, bufferName) inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 0) inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 1) inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 3) weightOutChannelVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 0) - weightInChannelMajorVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 1) - weightBandwidthVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 2) outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 0) outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 2) outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - # Map output dims to inputs dims - tilerModel.addConstraint(outputBatchVar == inputBatchVar) # Batch - tilerModel.addConstraint(outputChannelVar == weightOutChannelVar) # Output Channel - tilerModel.addConstraint(outputHeightVar == inputHeightVar) - tilerModel.addConstraint(outputWidthVar == inputWidthVar) - - tilerModel.addConstraint(inputHeightVar >= 1) - tilerModel.addConstraint(inputWidthVar >= 1) - - return tilerModel - - @staticmethod - def addPolicyConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - - # Get to-be-tiled tensor's buffers - inputBuffer = ctxt.lookup(name = parseDict['data_in']) - weightBuffer = ctxt.lookup(name = parseDict['weight']) - outputBuffer = ctxt.lookup(name = parseDict['data_out']) - - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 2) - inputChannelVar = tilerModel.getTensorDimVar(tensorName = inputBuffer.name, dimIdx = 3) - - weightOutChannelVar = tilerModel.getTensorDimVar(tensorName = weightBuffer.name, dimIdx = 0) - weightInChannelMajorVar = tilerModel.getTensorDimVar(tensorName = weightBuffer.name, dimIdx = 1) - weightBandwidthVar = tilerModel.getTensorDimVar(tensorName = weightBuffer.name, dimIdx = 2) - - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 2) - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBuffer.name, dimIdx = 3) - - strides = parseDict["strides"] - padding = parseDict["pads"] - - # LMACAN: Force full input channel to avoid partial results - tilerModel.addConstraint(inputChannelVar == inputChannelVar.Max()) - tilerModel.addConstraint(weightInChannelMajorVar == weightInChannelMajorVar.Max()) - tilerModel.addConstraint(weightBandwidthVar == weightBandwidthVar.Max()) - - tilerModel.addConstraint((inputHeightVar % strides[0]) == 0) - tilerModel.addConstraint((inputWidthVar % strides[1]) == 0) - - # N-EUREKA tile constraints to align with N-EUREKA's hardware subtiling - if parseDict["dim_im_out_x"] > 6: - tilerModel.addTileSizeDivisibleConstraint(parseDict, - "dim_im_out_x", - outputHeightVar, - 6, - strategy = PerformanceHint(priority = 3)) - else: - tilerModel.addConstraint(outputHeightVar == outputHeightVar.Max(), strategy = PerformanceHint(priority = 3)) - - if parseDict["dim_im_out_y"] > 6: - tilerModel.addTileSizeDivisibleConstraint(parseDict, - "dim_im_out_y", - outputWidthVar, - 6, - strategy = PerformanceHint(priority = 2)) - else: - tilerModel.addConstraint(outputWidthVar == outputWidthVar.Max(), strategy = PerformanceHint(priority = 2)) - - if parseDict["ch_im_out"] > 32: - tilerModel.addTileSizeDivisibleConstraint(parseDict, - "ch_im_out", - outputChannelVar, - 32, - strategy = PerformanceHint(priority = 1)) - else: - tilerModel.addConstraint(outputChannelVar == outputChannelVar.Max(), - strategy = PerformanceHint(priority = 1)) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['data_in', 'weight', 'data_out'] - inputBaseOffsets, outputBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, - operatorRepresentation, addrNames) - - varWeight = operatorRepresentation['weight'] - varOut = operatorRepresentation['data_out'] - - inputInCubes = [] - inputWeightCubes = [] - replacements: Dict[str, List[int]] = { - "padding_y_top": [], - "padding_y_bottom": [], - "padding_x_left": [], - "padding_x_right": [], - "dim_im_in_x_stride": [], - "dim_im_in_y_stride": [], - "dim_im_out_x_stride": [], - "dim_im_out_y_stride": [], - "input_addr_offset": [], - "nKo": [], - "nKi": [], - "nHo": [], - "nWo": [], - "bKo": [], - "bKi": [], - "bHo": [], - "bWo": [], - "bHi": [], - "bWi": [], - } - - replacementTypes = { - "padding_y_top": PointerClass(uint8_t), - "padding_y_bottom": PointerClass(uint8_t), - "padding_x_left": PointerClass(uint8_t), - "padding_x_right": PointerClass(uint8_t), - "dim_im_in_x_stride": PointerClass(uint32_t), - "dim_im_in_y_stride": PointerClass(uint32_t), - "dim_im_out_x_stride": PointerClass(uint32_t), - "dim_im_out_y_stride": PointerClass(uint32_t), - "input_addr_offset": PointerClass(uint32_t), - "nKo": PointerClass(uint16_t), - "nKi": PointerClass(uint16_t), - "nHo": PointerClass(uint16_t), - "nWo": PointerClass(uint16_t), - "bKo": PointerClass(uint16_t), - "bKi": PointerClass(uint16_t), - "bHo": PointerClass(uint16_t), - "bWo": PointerClass(uint16_t), - "bHi": PointerClass(uint16_t), - "bWi": PointerClass(uint16_t), - } - - weightH = operatorRepresentation['dim_kernel_y'] - weightW = operatorRepresentation['dim_kernel_x'] - weightC = operatorRepresentation['ch_im_in'] - - pads = operatorRepresentation['pads'] - strides = operatorRepresentation['strides'] - - for cube in outputCubes: - (BatchOffset, HOffset, WOffset, COffset) = cube.offset - (BatchSize, HSize, WSize, CSize) = cube.dims - - InCube, padding_tuple = Conv2DTileConstraint.computeInputCube((weightH, weightW), pads, strides, weightC, - cube, - ctxt.lookup(varOut).shape) - padding_left, padding_right, padding_top, padding_bottom = padding_tuple - - replacements['padding_y_top'].append(padding_top) - replacements['padding_y_bottom'].append(padding_bottom) - replacements['padding_x_left'].append(padding_left) - replacements['padding_x_right'].append(padding_right) - - inBSize, inHSize, inWSize, inCSize = InCube.dims - - dim_im_in_x_stride, dim_im_in_y_stride = ioStridesFromDimensions(inWSize, inCSize, - operatorRepresentation["input_bits"]) - replacements['dim_im_in_x_stride'].append(dim_im_in_x_stride) - replacements['dim_im_in_y_stride'].append(dim_im_in_y_stride) - dim_im_out_x_stride, dim_im_out_y_stride = ioStridesFromDimensions(WSize, CSize, - operatorRepresentation["output_bits"]) - replacements['dim_im_out_x_stride'].append(dim_im_out_x_stride) - replacements['dim_im_out_y_stride'].append(dim_im_out_y_stride) - - replacements['input_addr_offset'].append( - getInputAddrOffset(inWSize, dim_im_in_y_stride, padding_top, padding_left)) - - nKo, nKi, nHo, nWo, bKo, bKi, bHo, bWo, bHi, bWi = Neureka2DPWConvTemplate.getCounters( - inCSize, HSize, WSize, CSize, padding_bottom, padding_right, operatorRepresentation) - - replacements["nKo"].append(nKo) - replacements["nKi"].append(nKi) - replacements["nHo"].append(nHo) - replacements["nWo"].append(nWo) - replacements["bKo"].append(bKo) - replacements["bKi"].append(bKi) - replacements["bHo"].append(bHo) - replacements["bWo"].append(bWo) - replacements["bHi"].append(bHi) - replacements["bWi"].append(bWi) - - inputInCubes.append(InCube) - - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - - inputWeightCubes.append(WeightCube) - - inputLoadSchedule = [] - outputLoadSchedule = [] - - for a, b in zip(inputInCubes, inputWeightCubes): - inputLoadSchedule.append({"data_in": a, "weight": b}) - - for out in outputCubes: - outputLoadSchedule.append({"data_out": out}) - - tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) - variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) - - return variableReplacementSchedule, tilingSchedule - - -class NeurekaRQSPWConv2DTileConstraint(NeurekaPWConv2DTileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaPWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel - - @classmethod - def serializeTilingSolution( - cls, tilingSolution: NodeMemoryConstraint, absoluteOutputCubes: List[AbsoluteHyperRectangle], - targetMemLevel: str, ctxt: NetworkContext, - operatorRepresentation: OperatorRepresentation) -> Tuple[VariableReplacementScheme, TilingSchedule]: - variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( - tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - - addrNames = ['mul', 'add'] - inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, - addrNames) - newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - - inputRequantCubes = [] - for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) - newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] - - newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, - tilingSchedule.outputLoadSchedule) - - return variableReplacementSchedule, newTilingSchedule - - -class NeurekaWmemPWConv2DTileConstraint(TileConstraint): - - @staticmethod - def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - inputBufferName = parseDict['data_in'] - weightBufferName = parseDict['weight'] - outputBufferName = parseDict['data_out'] - - for bufferName in [inputBufferName, weightBufferName, outputBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - inputBatchVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 0) - inputHeightVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 1) - inputWidthVar = tilerModel.getTensorDimVar(tensorName = inputBufferName, dimIdx = 2) - - weightOutChannelVar = tilerModel.getTensorDimVar(tensorName = weightBufferName, dimIdx = 0) - - outputBatchVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 0) - outputHeightVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 1) - outputWidthVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 2) - # Map output dims to inputs dims tilerModel.addConstraint(outputBatchVar == inputBatchVar) tilerModel.addConstraint(outputHeightVar == inputHeightVar) tilerModel.addConstraint(outputWidthVar == inputWidthVar) - # Don't tile weights in weight memory - tilerModel.addConstraint(weightOutChannelVar == weightOutChannelVar.Max()) + weightBuffer = ctxt.lookup(weightBufferName) + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + tilerModel.addConstraint(weightOutChannelVar == weightOutChannelVar.Max()) + else: + tilerModel.addConstraint(weightOutChannelVar == outputChannelVar) tilerModel.addConstraint(inputHeightVar >= 1) tilerModel.addConstraint(inputWidthVar >= 1) @@ -418,7 +138,6 @@ def serializeTilingSolution( "padding_y_bottom": [], "padding_x_left": [], "padding_x_right": [], - "weight_addr_offset": [], "dim_im_in_x_stride": [], "dim_im_in_y_stride": [], "dim_im_out_x_stride": [], @@ -441,7 +160,6 @@ def serializeTilingSolution( "padding_y_bottom": PointerClass(uint8_t), "padding_x_left": PointerClass(uint8_t), "padding_x_right": PointerClass(uint8_t), - "weight_addr_offset": PointerClass(uint32_t), "dim_im_in_x_stride": PointerClass(uint32_t), "dim_im_in_y_stride": PointerClass(uint32_t), "dim_im_out_x_stride": PointerClass(uint32_t), @@ -466,14 +184,15 @@ def serializeTilingSolution( pads = operatorRepresentation['pads'] strides = operatorRepresentation['strides'] - for absoluteCube in absoluteOutputCubes: - cube = absoluteCube.rectangle + outputBuffer = ctxt.lookup(varOut) + assert isinstance(outputBuffer, VariableBuffer) + + for cube in outputCubes: (BatchOffset, HOffset, WOffset, COffset) = cube.offset (BatchSize, HSize, WSize, CSize) = cube.dims InCube, padding_tuple = Conv2DTileConstraint.computeInputCube((weightH, weightW), pads, strides, weightC, - cube, - ctxt.lookup(varOut).shape) + cube, outputBuffer.shape) padding_left, padding_right, padding_top, padding_bottom = padding_tuple replacements['padding_y_top'].append(padding_top) @@ -511,11 +230,6 @@ def serializeTilingSolution( inputInCubes.append(InCube) - _, _, _, absoluteCOffset = absoluteCube.absoluteOffset - weightShape = ctxt.lookup(varWeight).shape - WeightCube = HyperRectangle((absoluteCOffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) - replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, ctxt.lookup(varWeight))) - inputLoadSchedule = [] outputLoadSchedule = [] @@ -525,34 +239,39 @@ def serializeTilingSolution( for out in outputCubes: outputLoadSchedule.append({"data_out": out}) + weightBuffer = ctxt.lookup(varWeight) + assert isinstance(weightBuffer, VariableBuffer) + weightShape = weightBuffer.shape + + if hasattr(weightBuffer, "_memoryLevel") and weightBuffer._memoryLevel == "WeightMemory_SRAM": + replacements['weight_addr_offset'] = [] + replacementTypes['weight_addr_offset'] = PointerClass(uint32_t) + for absoluteCube in absoluteOutputCubes: + COffset, CSize = absoluteCube.absoluteOffset[-1], absoluteCube.rectangle.dims[-1] + WeightCube = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + replacements['weight_addr_offset'].append(calculateFlatOffsetInBytes(WeightCube, weightBuffer)) + else: + inputWeightBaseOffsets, outputWeightBaseOffsets = cls.extractBaseAddr(tilingSolution, targetMemLevel, + operatorRepresentation, ['weight']) + inputBaseOffsets.update(inputWeightBaseOffsets) + outputBaseOffsets.update(outputWeightBaseOffsets) + + for cube, load in zip(outputCubes, inputLoadSchedule): + COffset, CSize = cube.offset[-1], cube.dims[-1] + load['weight'] = HyperRectangle((COffset, 0, 0), (CSize, weightShape[-2], weightShape[-1])) + tilingSchedule = TilingSchedule(inputBaseOffsets, outputBaseOffsets, inputLoadSchedule, outputLoadSchedule) variableReplacementSchedule = VariableReplacementScheme(replacements, replacementTypes) return variableReplacementSchedule, tilingSchedule -class NeurekaWmemRQSPWConv2DTileConstraint(NeurekaWmemPWConv2DTileConstraint): +class NeurekaRQSPWConv2DTileConstraint(NeurekaPWConv2DTileConstraint): @staticmethod def addGeometricalConstraint(tilerModel: TilerModel, parseDict: Dict, ctxt: NetworkContext) -> TilerModel: - tilerModel = NeurekaWmemPWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) - - outputBufferName = parseDict['data_out'] - mulBufferName = parseDict['mul'] - addBufferName = parseDict['add'] - - # Add I/O dimensions to the model as variables - for bufferName in [mulBufferName, addBufferName]: - tilerModel.addTensorDimToModel(ctxt, bufferName) - - outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) - addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = 0) - mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = 0) - - tilerModel.addConstraint(outputChannelVar == addChannelVar) - tilerModel.addConstraint(outputChannelVar == mulChannelVar) - - return tilerModel + tilerModel = NeurekaPWConv2DTileConstraint.addGeometricalConstraint(tilerModel, parseDict, ctxt) + return requantAddGeometricalConstraint(tilerModel, parseDict, ctxt) @classmethod def serializeTilingSolution( @@ -562,22 +281,16 @@ def serializeTilingSolution( variableReplacementSchedule, tilingSchedule = super().serializeTilingSolution( tilingSolution, absoluteOutputCubes, targetMemLevel, ctxt, operatorRepresentation) - outputCubes = [cube.rectangle for cube in absoluteOutputCubes] - addrNames = ['mul', 'add'] inputRequantBaseOffsets, _ = cls.extractBaseAddr(tilingSolution, targetMemLevel, operatorRepresentation, addrNames) newInputBaseOffsets = {**tilingSchedule.inputBaseOffsets, **inputRequantBaseOffsets} - inputRequantCubes = [] - for cube in outputCubes: - (_, _, _, COffset) = cube.offset - (_, _, _, CSize) = cube.dims - inputRequantCubes.append(HyperRectangle((COffset,), (CSize,))) + requantSchedule = requantLoadSchedule(absoluteOutputCubes, ctxt, operatorRepresentation) newInputLoadSchedule = [{ - **schedule, "add": requant, - "mul": requant - } for schedule, requant in zip(tilingSchedule.inputLoadSchedule, inputRequantCubes)] + **load, + **rqLoad + } for load, rqLoad in zip(tilingSchedule.inputLoadSchedule, requantSchedule)] newTilingSchedule = TilingSchedule(newInputBaseOffsets, tilingSchedule.outputBaseOffsets, newInputLoadSchedule, tilingSchedule.outputLoadSchedule) diff --git a/Deeploy/Targets/Neureka/TileConstraints/RequantHelpers.py b/Deeploy/Targets/Neureka/TileConstraints/RequantHelpers.py new file mode 100644 index 0000000000..e1e4b16aea --- /dev/null +++ b/Deeploy/Targets/Neureka/TileConstraints/RequantHelpers.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import Dict, List + +from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation +from Deeploy.TilingExtension.TilerModel import TilerModel +from Deeploy.TilingExtension.TilingCodegen import AbsoluteHyperRectangle, HyperRectangle + + +def requantAddGeometricalConstraint(tilerModel: TilerModel, operatorRepresentation: OperatorRepresentation, + ctxt: NetworkContext) -> TilerModel: + outputBufferName = operatorRepresentation['data_out'] + mulBufferName = operatorRepresentation['mul'] + addBufferName = operatorRepresentation['add'] + + # Add I/O dimensions to the model as variables + for bufferName in [mulBufferName, addBufferName]: + tilerModel.addTensorDimToModel(ctxt, bufferName) + + outputChannelVar = tilerModel.getTensorDimVar(tensorName = outputBufferName, dimIdx = 3) + + addBuffer = ctxt.lookup(addBufferName) + addChannelVar = tilerModel.getTensorDimVar(tensorName = addBufferName, dimIdx = len(addBuffer.shape) - 1) + mulBuffer = ctxt.lookup(mulBufferName) + mulChannelVar = tilerModel.getTensorDimVar(tensorName = mulBufferName, dimIdx = len(mulBuffer.shape) - 1) + + tilerModel.addConstraint(outputChannelVar == addChannelVar) + tilerModel.addConstraint(outputChannelVar == mulChannelVar) + + return tilerModel + + +def requantLoadSchedule( + absoluteOutputCubes: List[AbsoluteHyperRectangle], + ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation, +) -> List[Dict[str, HyperRectangle]]: + outputCubes = [cube.rectangle for cube in absoluteOutputCubes] + + shapeMul = ctxt.lookup(operatorRepresentation["mul"]).shape + shapeAdd = ctxt.lookup(operatorRepresentation["add"]).shape + + schedule = [] + for cube in outputCubes: + (_, _, _, COffset) = cube.offset + (_, _, _, CSize) = cube.dims + MulCube = HyperRectangle((0,) * (len(shapeMul) - 1) + (COffset,), (1,) * (len(shapeMul) - 1) + (CSize,)) + AddCube = HyperRectangle((0,) * (len(shapeAdd) - 1) + (COffset,), (1,) * (len(shapeAdd) - 1) + (CSize,)) + schedule.append({"mul": MulCube, "add": AddCube}) + + return schedule diff --git a/Deeploy/Targets/Neureka/Tiler.py b/Deeploy/Targets/Neureka/Tiler.py index 775294d8e0..dda00930c0 100644 --- a/Deeploy/Targets/Neureka/Tiler.py +++ b/Deeploy/Targets/Neureka/Tiler.py @@ -4,16 +4,13 @@ from Deeploy.Targets.Neureka.Bindings import NeurekaDenseConv2DBindings, NeurekaDWConv2DBindings, \ - NeurekaPWConv2DBindings, NeurekaRQSDenseConv2DBindings, NeurekaRQSDWConv2DBindings, NeurekaRQSPWConv2DBindings, \ - NeurekaWmemDenseConv2DBindings, NeurekaWmemDWConv2DBindings, NeurekaWmemPWConv2DBindings, \ - NeurekaWmemRQSDenseConv2DBindings, NeurekaWmemRQSDWConv2DBindings, NeurekaWmemRQSPWConv2DBindings + NeurekaPWConv2DBindings, NeurekaRQSDenseConv2DBindings, NeurekaRQSDWConv2DBindings, NeurekaRQSPWConv2DBindings from Deeploy.Targets.Neureka.TileConstraints.NeurekaDenseConstraint import NeurekaDenseConv2DTileConstraint, \ - NeurekaRQSDenseConv2DTileConstraint, NeurekaWmemDenseConv2DTileConstraint, \ - NeurekaWmemRQSDenseConv2DTileConstraint + NeurekaRQSDenseConv2DTileConstraint from Deeploy.Targets.Neureka.TileConstraints.NeurekaDepthwiseConstraint import NeurekaDWConv2DTileConstraint, \ - NeurekaRQSDWConv2DTileConstraint, NeurekaWmemDWConv2DTileConstraint, NeurekaWmemRQSDWConv2DTileConstraint + NeurekaRQSDWConv2DTileConstraint from Deeploy.Targets.Neureka.TileConstraints.NeurekaPointwiseConstraint import NeurekaPWConv2DTileConstraint, \ - NeurekaRQSPWConv2DTileConstraint, NeurekaWmemPWConv2DTileConstraint, NeurekaWmemRQSPWConv2DTileConstraint + NeurekaRQSPWConv2DTileConstraint from Deeploy.TilingExtension.TilerExtension import TilingReadyNodeBindings NeurekaRQSPWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaRQSPWConv2DBindings, @@ -21,27 +18,12 @@ NeurekaPWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaPWConv2DBindings, tileConstraint = NeurekaPWConv2DTileConstraint()) -NeurekaWmemRQSPWConv2DTilingReadyBindings = TilingReadyNodeBindings( - nodeBindings = NeurekaWmemRQSPWConv2DBindings, tileConstraint = NeurekaWmemRQSPWConv2DTileConstraint()) -NeurekaWmemPWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaWmemPWConv2DBindings, - tileConstraint = NeurekaWmemPWConv2DTileConstraint()) - NeurekaRQSDWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaRQSDWConv2DBindings, tileConstraint = NeurekaRQSDWConv2DTileConstraint()) NeurekaDWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaDWConv2DBindings, tileConstraint = NeurekaDWConv2DTileConstraint()) -NeurekaWmemRQSDWConv2DTilingReadyBindings = TilingReadyNodeBindings( - nodeBindings = NeurekaWmemRQSDWConv2DBindings, tileConstraint = NeurekaWmemRQSDWConv2DTileConstraint()) -NeurekaWmemDWConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaWmemDWConv2DBindings, - tileConstraint = NeurekaWmemDWConv2DTileConstraint()) - NeurekaRQSDenseConv2DTilingReadyBindings = TilingReadyNodeBindings( nodeBindings = NeurekaRQSDenseConv2DBindings, tileConstraint = NeurekaRQSDenseConv2DTileConstraint()) NeurekaDenseConv2DTilingReadyBindings = TilingReadyNodeBindings(nodeBindings = NeurekaDenseConv2DBindings, tileConstraint = NeurekaDenseConv2DTileConstraint()) - -NeurekaWmemRQSDenseConv2DTilingReadyBindings = TilingReadyNodeBindings( - nodeBindings = NeurekaWmemRQSDenseConv2DBindings, tileConstraint = NeurekaWmemRQSDenseConv2DTileConstraint()) -NeurekaWmemDenseConv2DTilingReadyBindings = TilingReadyNodeBindings( - nodeBindings = NeurekaWmemDenseConv2DBindings, tileConstraint = NeurekaWmemDenseConv2DTileConstraint()) From 41baa7bd6c784db362422eb2d07731a0d53c37cc Mon Sep 17 00:00:00 2001 From: Luka Macan Date: Mon, 27 Oct 2025 13:51:09 +0100 Subject: [PATCH 16/28] Disallow shape inference (#128) The current status quo did shape inference on _some_ layers but not all. This was done through the `computeShapes` method of the ONNXLayer and by examining the implementations of that method, we can see that some calculate the output shape out of the input shapes, but some just blindly copy the tensor's shape. I propose we disallow shape inference and if we want to properly support this feature we can revert this change and implement it properly or depend on another tool to do it for us (e.g. [ONNX's shape inference module](https://onnx.ai/onnx/api/shape_inference.html)). Now, I have disallowed shape inference after lowering because some lowerings actually consumed shapeless tensors and produced correct replacements, but some lowerings produced shapeless tensors themeselves, specifically, the MHSA pass in MemPool. I have disabled all tests that used those lowerings which can be re-enabled once the offending lowerings get fixed. I will create an issue following this if this PR gets accepted. ## Added - Added assertion that all the graph tensors after lowering have a shape annotated ## Changed - Disabled ICCT_ITA_8 MemPool test because it was using a lowering that created shapeless tensors - Added missing shape annotation to the testTypeInferenceDifferentTypes --- .github/workflows/ci-platform-mempool.yml | 1 - CHANGELOG.md | 4 ++++ Deeploy/DeeployTypes.py | 8 ++++++++ .../network.onnx | Bin 202 -> 229 bytes 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-platform-mempool.yml b/.github/workflows/ci-platform-mempool.yml index 7f716e2dab..f7394c04da 100644 --- a/.github/workflows/ci-platform-mempool.yml +++ b/.github/workflows/ci-platform-mempool.yml @@ -69,6 +69,5 @@ jobs: ICCT ICCT_ITA ICCT_8 - ICCT_ITA_8 miniMobileNet miniMobileNetv2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 357a2a39e0..a567305e2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Disallow shape inference [#128](https://github.com/pulp-platform/Deeploy/pull/128) - Remove memory-aware node bindings [#123](https://github.com/pulp-platform/Deeploy/pull/123) - Fix missing const's layout transformation and refactor NCHWtoNHWC passes [#122](https://github.com/pulp-platform/Deeploy/pull/122) - Fix aliasing [#125](https://github.com/pulp-platform/Deeploy/pull/125) @@ -51,6 +52,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Per–memory-level usage tracking and worst-case reporting in `NetworkContext` - Memory/I/O summaries and input/output logging in deployers - RequantHelpers.py for Neureka's TileConstraints +- Added assertion that all the graph tensors after lowering have a shape annotated ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -85,6 +87,8 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Removed NodeMemoryLevelChecker, MemoryAwareNodeBinding - Removed _parseNode from MemoryNetworkDeployer since we don't need the annotations before typeChecking anymore - Removed Wmem variants of bindings and tile constraints from Neureka +- Disabled ICCT_ITA_8 MemPool test because it was using a lowering that created shapeless tensors +- Added missing shape annotation to the testTypeInferenceDifferentTypes ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index 936931c2e6..8c2f5d2485 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -3372,6 +3372,11 @@ def _removeIdentityNodes(self): for node in filter(lambda x: x.op == "Identity", self.graph.nodes): self.graph.deleteNode(node) + def _assertTensorsHaveShape(self) -> None: + missingShapes = [name for name, tensor in self.graph.tensors().items() if tensor.shape is None] + assert len(missingShapes) == 0, \ + f"Shape inference is not supported.\nFound tensors with missing shape annotation: {missingShapes}" + def frontEnd(self): """API hook to prepare the graph to be deployed and build the initial NetworkContext @@ -3419,6 +3424,9 @@ def frontEnd(self): log.info(f"> Export State {_middlewarePostLoweringFilename}[.onnx|.pkl]") self.exportDeeployState(self.deeployStateDir, _middlewarePostLoweringFilename) + log.info(" - Assert all tensors have a shape annotation") + self._assertTensorsHaveShape() + log.info("- Perform Graph Parsing") try: self.parse(self.default_channels_first) # This reparses the lowered graph diff --git a/DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx b/DeeployTest/Tests/testTypeInferenceDifferentTypes/network.onnx index 588abf934444d23c931e3beaaac4e03405482648..e04e330731a5bda9442dfa95b38d0ddb8b1beb8d 100644 GIT binary patch delta 53 zcmX@b_>_@@gHwn>ioxpIL=inf@%+5Jium-R#Da|C(xUX#{E6PxtXa}rj1dzjO0YSx Ja4`sQ0|2924!QsU delta 46 vcmaFLc#2VkgHwnvF(oBFIU_MMFTNzTxWsDXL=HVpewg4y_i7d=CIMjpT3HT8 From 23e9f0281e88dfd236358646e411126fa24b131d Mon Sep 17 00:00:00 2001 From: Alex Marchioni Date: Fri, 31 Oct 2025 10:40:18 +0100 Subject: [PATCH 17/28] fix bug in Generic GEMM with no bias (#126) In generic platform, GEMM was not correctly hoisting the bias tensor when required. To solve the issue, bias hoisting has been moved from `MatMulParser.parseNodeCtxt` to `GEMMParser.parseNode`. Moreover, the default value of `noBiasHoisting` flag in `GenericGEMMParser` has been changed from True to False to be compliant with the template. ## Added - testFloatGEMMnobias ## Changed - Generic\Parser.py file (`MatMulParser`, `GEMMParser`, and `GenericGEMMParser`) ## Fixed - fix bias hoisting in GEMM with no bias Co-authored-by: Alex Marchioni --- CHANGELOG.md | 3 ++ Deeploy/Targets/Generic/Parsers.py | 29 ++++-------------- .../Tests/testFloatGEMMnobias/inputs.npz | Bin 0 -> 4360 bytes .../Tests/testFloatGEMMnobias/network.onnx | Bin 0 -> 9754 bytes .../Tests/testFloatGEMMnobias/outputs.npz | Bin 0 -> 2314 bytes 5 files changed, 9 insertions(+), 23 deletions(-) create mode 100644 DeeployTest/Tests/testFloatGEMMnobias/inputs.npz create mode 100644 DeeployTest/Tests/testFloatGEMMnobias/network.onnx create mode 100644 DeeployTest/Tests/testFloatGEMMnobias/outputs.npz diff --git a/CHANGELOG.md b/CHANGELOG.md index a567305e2b..4cdb588d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) - Fix `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) [#119](https://github.com/pulp-platform/Deeploy/pull/119) +- Fix bias hoisting in generic GEMM with no bias [#126](https://github.com/pulp-platform/Deeploy/pull/126) ### Added - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough @@ -53,6 +54,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Memory/I/O summaries and input/output logging in deployers - RequantHelpers.py for Neureka's TileConstraints - Added assertion that all the graph tensors after lowering have a shape annotated +- Added testFloatGEMMnobias ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -102,6 +104,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Fixed aliasing - Missing layout transformation of the const's (bias, mul, add, shift in Conv/RequantizedConv) - Keep mul/add rank of requantized Neureka tile constraints +- Fix bias hoisting in generic GEMM with no bias ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index 7752834c50..f63bb5411d 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -1682,14 +1682,6 @@ def parseNodeCtxt(self, for idx, outputNode in enumerate(node.outputs): self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name - # Create fake C node for GEMM-compatibility and hoist it - if not self.noBiasHoisting: - values = np.zeros(ctxt.lookup(node.inputs[0].name).shape, dtype = inputNode.dtype) - zeroTensor = gs.Constant(f'{node.name}_C_Tensor', values = values) - ctxt.hoistConstant(zeroTensor, _type = ctxt.lookup(inputNode.name)._type) - node.inputs.append(zeroTensor) - self.operatorRepresentation['C'] = f'{node.name}_C_Tensor' - # Store the input and output shapes in the operator representation self.operatorRepresentation['size'] = np.prod(ctxt.lookup(node.inputs[0].name).shape) self.operatorRepresentation['A_shape'] = ctxt.lookup(node.inputs[0].name).shape @@ -1772,8 +1764,7 @@ def parseNodeCtxt(self, class GEMMParser(MatMulParser): def __init__(self, noBiasHoisting = True): - self.noBiasHoisting = noBiasHoisting - super().__init__() + super().__init__(noBiasHoisting) def parseNode(self, node: gs.Node) -> (bool): @@ -1805,6 +1796,10 @@ def parseNode(self, node: gs.Node) -> (bool): else: self.operatorRepresentation['transB'] = 0 + if len(node.inputs) == 2 and not self.noBiasHoisting: + C = gs.Constant(f"{node.name}_C", np.zeros((1,))) + node.inputs.append(C) + return True # This might be a matmul node -> Cast up else: @@ -1836,18 +1831,6 @@ def parseNodeCtxt(self, # Create flag for same dimension between bias matrix and the final batch dimension self.operatorRepresentation['C_batched'] = (self.operatorRepresentation['batch'] == np.prod( newCtxt.lookup(node.inputs[2].name).shape[:-2])) - elif not self.noBiasHoisting: - # Create mock bias matrix if not present in the inputs - values = np.zeros((1)) - zeroTensor = gs.Constant(f'{node.name}_C_Tensor', values = values) - newCtxt.hoistConstant(zeroTensor) - - # Store it in the operator representation - self.operatorRepresentation['C'] = f'{node.name}_C_Tensor' - self.operatorRepresentation['C_shape'] = (0,) - - # Create flag for same dimension between bias matrix and the final batch dimension - self.operatorRepresentation['C_batched'] = False self.operatorRepresentation['size'] = np.prod(newCtxt.lookup(node.inputs[0].name).shape) @@ -2324,7 +2307,7 @@ def parseNodeCtxt(self, class GenericGEMMParser(GEMMParser): - def __init__(self, noBiasHoisting = True): + def __init__(self, noBiasHoisting = False): super().__init__(noBiasHoisting) def parseNode(self, node: gs.Node) -> (bool): diff --git a/DeeployTest/Tests/testFloatGEMMnobias/inputs.npz b/DeeployTest/Tests/testFloatGEMMnobias/inputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..47728a36083b62e0eba484ed9d9c2978a41ffa9b GIT binary patch literal 4360 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 F{{pKCDzX3o literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testFloatGEMMnobias/network.onnx b/DeeployTest/Tests/testFloatGEMMnobias/network.onnx new file mode 100644 index 0000000000000000000000000000000000000000..59264acd46214498e839ba287a17feb421613a5e GIT binary patch literal 9754 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 Iz`*Fg02PZ)*Z=?k literal 0 HcmV?d00001 diff --git a/DeeployTest/Tests/testFloatGEMMnobias/outputs.npz b/DeeployTest/Tests/testFloatGEMMnobias/outputs.npz new file mode 100644 index 0000000000000000000000000000000000000000..4e0debdf54de9fcbe825edaf722bfba1f464cafb GIT binary patch literal 2314 zcmbW3c~s8p7RTRuNxgB(80yrEMw*lH{p}r+Xe6Of(u6womO>{(WQsHxQyG&Ix*Z|W zZ|@9+GSw1CaX1%c=*p1fWH@!tx$Ca`@BQxeJm2+v*IsM?_w0|Si?o}CYBC#xg<~ry|joB&h$@_aEQk?(OF3qas-*i8l!fUK$u}GEQ!y2pMT& zE;k8@jE;#8i13e$4hrtdodUv_26yI57X>JTJKv@@qs--Ywr1w?Rr3E+vc}paSYN9S z)l~x((~U<8hT1dfva1b7xyDe=_nm@5U&{H#yFt7D2S~eX!j})5u#Zn0EuZa5cdoe8 zHs7JR^Sd>AzA1-y@9znbAEW7I;dzB?`#j<4>q})at*bQgR~h^`-+!3X*`#C57HE4zT!^j*B zdLLtn(zCyi)BQ+r-g{mAOz-H}*>r5x9R%4A9ck=MDb#0`(1+BMqG7re&e>?PqPan= zGHwQs(A$E_y$oome@c(jiy>~j7rj1|!qEu}(83gWbK3MW77HglQJV=keY3{=(s=Uua1qkN zuZq9h1!7qE5InGGJnw!vhD~eqNPTq+oLKY``l|el>iNddmaE1Zp|Ru^@UhIRwE*Gk zev)*bfGrtIz`?XqNP4Kpb_RWg8_M@!EB!9IEwJJIHf>npHk$2m4$ItE@t_|=xKCgz zOr2wdPyLzH&Wz?8lU8w{hnx>Oh-J$+4Z|}veNo*X!0=EMWTvg1(QlH_A%k)?8iQ=s1+Mc4w2y zxN0o;`V)oz$tp6_={BgP$FK!9L!1kVaWnmaO+hns++Xww3_E4^4yJ%M! zj^B0+!utnC(!sH#amR^y;v!W`)>D&m_xZQz;Yu}DxmGDyy}AJ2k&QTTZ3M2^mLZf> zOyXPK>#)ssG#g5#;waNp(D{@LmapTlIkh*XL2Up&QU1ytxLvHQh7mE%Z#S=r}81O!rY-g?3(Ju(Y*`dUUyZtJ81+Z&2z<*G3TIXpKYx9K$Caf z?g^zyd8pd7kyRhlDdZcYl9zV(bPi>Ys!yj+a=s;wD}5Z6d{HSI$!{ zz}QADuC=kn-dBt0Vy{VbGwY(5awU!`7N4c%xs~AG`EO6FvJ%RTEzlxQCN5P!59wQs zK>1rQ*tF#xoNJQcZ;y;2X0<(P8x~P*yc(~vaHo`L4{$iO1?J99&=|+Zp8mAdJHQMJQ|n#_7WU$(8kbzG?fX7)^NGy8Rd=9p*bC8U%^-0D$EMA=V56n>{ai8o>S6!%x@>5zIHXV)Ty$k ri;Aj+^ndB4i%q(Y>~E&&vILc``@byX>C#=TD^cmJF`ZuaZ?5?h!ND6` literal 0 HcmV?d00001 From 397341fd8afc0a460077df593c77449075e0a1e5 Mon Sep 17 00:00:00 2001 From: Philip Wiese Date: Tue, 4 Nov 2025 11:11:51 +0100 Subject: [PATCH 18/28] Support Fully Asynchronous DMAs (#114) This pull request introduces improvements to the DMA code generation for several backends (`SnitchDma` and `Mchan`), to enable proper double-buffering by overlapping DMA transfers with kernel calls. Additionally, it refactors the profiling infrastructure for Snitch tiling and improves the readability of the generated code by adding some helpful comments. ### Added - Profiling-aware tiling mixins: `ProfilingDoubleBufferingTilingMixIn` and `ProfilingSingleBufferingTilingMixIn` integrated into the Snitch and PULP tiling generators. - Optional comments injected into generated code (DMA templates `_initTemplate`, `_allocTemplate`, `_waitTemplate`) for improved readability and traceability. - Profiling instrumentation for tile-level DMA and kernel execution integrated into the tiling passes for Snitch backends. ### Changed - Refactored DMA code-generation in the backends (`SnitchDma`, `Mchan`) to enable full overlap of DMA and compute for double-buffering, replacing the earlier (incorrect) synchronization scheme. - Simplified tiling generator logic by leveraging the profiling mix-ins and consolidating redundant template assignments, improving maintainability and code generation clarity. - Improved the waiting-strategy architecture: introduced `PerTensorWaitingStrategy` alongside existing `TensorGroupWaitingStrategy`, enabling finer-grained control of DMA futures in DB mode. ### Fixed - Corrected DMA synchronization bug that previously prevented effective overlapping of transfer and compute in DB mode, especially noticeable for memory-bound kernels. --- CHANGELOG.md | 5 + .../PULPClusterTiling.py | 10 +- .../CodeTransformationPasses/PULPL3Tiling.py | 10 +- Deeploy/Targets/PULPOpen/DMA/L3Dma.py | 11 +- Deeploy/Targets/PULPOpen/DMA/MchanDma.py | 19 +- Deeploy/Targets/Snitch/Bindings.py | 3 +- .../SnitchClusterTiling.py | 39 +- Deeploy/Targets/Snitch/DMA/SnitchDma.py | 26 +- Deeploy/TilingExtension/AsyncDma.py | 85 +++-- .../DoubleBufferingTilingCodeGeneration.py | 308 ++++++++++----- .../SingleBufferingTilingCodeGeneration.py | 146 +++++--- .../TilingCodeGeneration.py | 31 +- .../TilingPrototypes.py | 351 +++--------------- DeeployTest/Platforms/Snitch/main.c | 17 +- TargetLibraries/PULPOpen/inc/mchan_v6.h | 9 +- TargetLibraries/PULPOpen/inc/mchan_v7.h | 9 +- TargetLibraries/Snitch/src/CycleCounter.c | 15 +- 17 files changed, 584 insertions(+), 510 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cdb588d57..faf4de42c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- Support Fully Asynchronous DMAs [#114](https://github.com/pulp-platform/Deeploy/pull/114) - Disallow shape inference [#128](https://github.com/pulp-platform/Deeploy/pull/128) - Remove memory-aware node bindings [#123](https://github.com/pulp-platform/Deeploy/pull/123) - Fix missing const's layout transformation and refactor NCHWtoNHWC passes [#122](https://github.com/pulp-platform/Deeploy/pull/122) @@ -55,6 +56,8 @@ This file contains the changelog for the Deeploy project. The changelog is divid - RequantHelpers.py for Neureka's TileConstraints - Added assertion that all the graph tensors after lowering have a shape annotated - Added testFloatGEMMnobias +- Profiling support and optional comments in generated DMA code for better traceability +- Added new waiting-strategy logic with fine-grained `PerTensorWaitingStrategy` ### Changed - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. @@ -91,6 +94,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Removed Wmem variants of bindings and tile constraints from Neureka - Disabled ICCT_ITA_8 MemPool test because it was using a lowering that created shapeless tensors - Added missing shape annotation to the testTypeInferenceDifferentTypes +- Refactored DMA code generation (`SnitchDma`, `Mchan`) to correctly overlap transfers and compute in double-buffering mode ### Fixed - Prevent node duplication for graphs generated via GraphSurgeon @@ -105,6 +109,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Missing layout transformation of the const's (bias, mul, add, shift in Conv/RequantizedConv) - Keep mul/add rank of requantized Neureka tile constraints - Fix bias hoisting in generic GEMM with no bias +- DMA synchronization bug causing reduced DB performance on memory-bound kernels. ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py index 7f503a5da3..3c0bba3107 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPClusterTiling.py @@ -7,14 +7,12 @@ from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity from Deeploy.TilingExtension.AsyncDma import AsyncDma from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ - DoubleBufferingTilingCodeGeneration + DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ - SingleBufferingTilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ - ProfilingDoubleBufferingTilingMixIn, ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingMixIn + ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingCodeGeneration -class PULPClusterTilingGenerationSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): +class PULPClusterTilingGenerationSB(SingleBufferingTilingCodeGeneration): pass @@ -22,7 +20,7 @@ class ProfilingPULPClusterTilingGenerationSB(SingleBufferingTilingCodeGeneration pass -class PULPClusterTilingGenerationDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): +class PULPClusterTilingGenerationDB(DoubleBufferingTilingCodeGeneration): pass diff --git a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py index 646f179d9c..9df0d88479 100644 --- a/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py +++ b/Deeploy/Targets/PULPOpen/CodeTransformationPasses/PULPL3Tiling.py @@ -7,14 +7,12 @@ from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity from Deeploy.TilingExtension.AsyncDma import AsyncDma from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ - DoubleBufferingTilingCodeGeneration + DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ - SingleBufferingTilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ - ProfilingDoubleBufferingTilingMixIn, ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingMixIn + ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingCodeGeneration -class PULPL3TilingGenerationSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): +class PULPL3TilingGenerationSB(SingleBufferingTilingCodeGeneration): pass @@ -22,7 +20,7 @@ class ProfilingPULPL3TilingGenerationSB(SingleBufferingTilingCodeGeneration, Pro pass -class PULPL3TilingGenerationDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): +class PULPL3TilingGenerationDB(DoubleBufferingTilingCodeGeneration): pass diff --git a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py index 849db08576..6c2aa30811 100644 --- a/Deeploy/Targets/PULPOpen/DMA/L3Dma.py +++ b/Deeploy/Targets/PULPOpen/DMA/L3Dma.py @@ -12,9 +12,16 @@ class L3DmaFuture(Future): - _initTemplate = NodeTemplate("pi_cl_ram_req_t ${name};") + _initTemplate = NodeTemplate("pi_cl_ram_req_t ${name} = {0};") + _deinitTemplate = NodeTemplate("") - _waitTemplate = NodeTemplate("pi_cl_ram_copy_wait(&${name});") + + _allocTemplate = NodeTemplate("") + + _waitTemplate = NodeTemplate(""" + if (${name}.size != 0) { + pi_cl_ram_copy_wait(&${name}); + }""") class L3Dma(AsyncDma): diff --git a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py index a640973672..93bf699dc6 100644 --- a/Deeploy/Targets/PULPOpen/DMA/MchanDma.py +++ b/Deeploy/Targets/PULPOpen/DMA/MchanDma.py @@ -6,14 +6,23 @@ from typing import Dict, Tuple from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer -from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future, TensorGroupWaitingStrategy +from Deeploy.TilingExtension.AsyncDma import AsyncDma, DirectionWaitingStrategy, DmaDirection, Future class MchanChannelFuture(Future): - _initTemplate = NodeTemplate("uint32_t ${name} = mchan_channel_alloc();") - _deinitTemplate = NodeTemplate("mchan_channel_free(${name});") - _waitTemplate = NodeTemplate("mchan_channel_wait(${name});") + _initTemplate = NodeTemplate("uint32_t ${name} = (uint32_t) -1;") + + _deinitTemplate = NodeTemplate("") + + _allocTemplate = NodeTemplate("${name} = mchan_channel_alloc();") + + _waitTemplate = NodeTemplate(""" +if (${name} <= MCHAN_CHANNEL_ID_MAX) { + mchan_channel_wait(${name}); + mchan_channel_free(${name}); +} +""") class MchanDma(AsyncDma): @@ -22,7 +31,7 @@ class MchanDma(AsyncDma): 1: NodeTemplate("mchan_transfer_1d(${cmd}, ${loc}, ${ext});"), 2: NodeTemplate("mchan_transfer_2d_ext_strided(${cmd}, ${loc}, ${ext}, ${size_1d}, ${stride_2d});"), } - _waitingStrategy = TensorGroupWaitingStrategy(MchanChannelFuture, "channel_id") + _waitingStrategy = DirectionWaitingStrategy(MchanChannelFuture, "channel") def __init__(self, transferTemplates: Dict[int, NodeTemplate] = _transferTemplates) -> None: super().__init__(transferTemplates) diff --git a/Deeploy/Targets/Snitch/Bindings.py b/Deeploy/Targets/Snitch/Bindings.py index e9be18a535..25b150b553 100644 --- a/Deeploy/Targets/Snitch/Bindings.py +++ b/Deeploy/Targets/Snitch/Bindings.py @@ -14,7 +14,7 @@ from Deeploy.Targets.Generic.Templates import iNoNormTemplate from Deeploy.Targets.Generic.TypeCheckers import AddChecker, GEMMChecker, RQAddChecker, SoftmaxChecker, iNoNormChecker from Deeploy.Targets.Snitch.CodeTransformationPasses import SnitchClusterTiling, SnitchCoreFilterPass, \ - SnitchProfileExecutionBlockPass, SnitchSynchCoresPass + SnitchSynchCoresPass from Deeploy.Targets.Snitch.DMA.SnitchDma import SnitchDma from Deeploy.Targets.Snitch.Templates import AddTemplate, FloatGemmTemplate, RQAddTemplate, iSoftmaxTemplate from Deeploy.Targets.Snitch.Templates.FloatSoftmaxTemplate import FloatSoftmax_Template @@ -37,7 +37,6 @@ TiledTransformer = CodeTransformation([ SnitchCoreFilterPass("compute"), - SnitchProfileExecutionBlockPass(), TilingVariableReplacement("L1"), TilingCallClosure(writeback = False), SnitchSynchCoresPass(), diff --git a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py index 30213d3147..e8204f6ae2 100644 --- a/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py +++ b/Deeploy/Targets/Snitch/CodeTransformationPasses/SnitchClusterTiling.py @@ -4,29 +4,45 @@ from typing import Tuple -from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, _NoVerbosity +from Deeploy.DeeployTypes import CodeGenVerbosity, CodeTransformationPass, ExecutionBlock, NetworkContext, \ + NodeTemplate, _NoVerbosity from Deeploy.TilingExtension.AsyncDma import AsyncDma from Deeploy.TilingExtension.CodeTransformationPasses.DoubleBufferingTilingCodeGeneration import \ - DoubleBufferingTilingCodeGeneration + DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn from Deeploy.TilingExtension.CodeTransformationPasses.SingleBufferingTilingCodeGeneration import \ - SingleBufferingTilingCodeGeneration -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import DoubleBufferingTilingMixIn, \ - SingleBufferingTilingMixIn + ProfilingSingleBufferingTilingMixIn, SingleBufferingTilingCodeGeneration -class SnitchClusterTilingSB(SingleBufferingTilingCodeGeneration, SingleBufferingTilingMixIn): +class SnitchClusterTilingSB(SingleBufferingTilingCodeGeneration): pass -class SnitchClusterTilingDB(DoubleBufferingTilingCodeGeneration, DoubleBufferingTilingMixIn): +class SnitchClusterTilingDB(DoubleBufferingTilingCodeGeneration): pass +class ProfilingSnitchClusterTilingSB(SingleBufferingTilingCodeGeneration, ProfilingSingleBufferingTilingMixIn): + _printCycleDifference = NodeTemplate(r""" + printf("%s%u][Core %d] %s%u%s", ${prefixStr}, ${profileIdxVar}, snrt_global_core_idx(), "${flavorStr}", \ + ${measurementsEnd}[${profileIdxVar}] - ${measurementsStart}[${profileIdxVar}], ${suffixStr}); + """) + + +class ProfilingSnitchClusterTilingDB(DoubleBufferingTilingCodeGeneration, ProfilingDoubleBufferingTilingMixIn): + _printCycleDifference = NodeTemplate(r""" + printf("%s%u][Core %d] %s%u%s", ${prefixStr}, ${profileIdxVar}, snrt_global_core_idx(), "${flavorStr}", \ + ${measurementsEnd}[${profileIdxVar}] - ${measurementsStart}[${profileIdxVar}], ${suffixStr}); + """) + + class SnitchClusterTiling(CodeTransformationPass): def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): self.SB = SnitchClusterTilingSB(externalMemory, localMemory, dma) + self.profilingSB = ProfilingSnitchClusterTilingSB(externalMemory, localMemory, dma) + self.DB = SnitchClusterTilingDB(externalMemory, localMemory, dma) + self.profilingDB = ProfilingSnitchClusterTilingDB(externalMemory, localMemory, dma) def apply(self, ctxt: NetworkContext, @@ -34,8 +50,9 @@ def apply(self, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: if verbose.tilingProfiling: - raise NotImplementedError("Profiling not implemented for L2") - - ctxt, executionBlock = self.SB.apply(ctxt, executionBlock, name) - ctxt, executionBlock = self.DB.apply(ctxt, executionBlock, name) + ctxt, executionBlock = self.profilingSB.apply(ctxt, executionBlock, name) + ctxt, executionBlock = self.profilingDB.apply(ctxt, executionBlock, name) + else: + ctxt, executionBlock = self.SB.apply(ctxt, executionBlock, name) + ctxt, executionBlock = self.DB.apply(ctxt, executionBlock, name) return ctxt, executionBlock diff --git a/Deeploy/Targets/Snitch/DMA/SnitchDma.py b/Deeploy/Targets/Snitch/DMA/SnitchDma.py index aea1f03007..ac0c622cc8 100644 --- a/Deeploy/Targets/Snitch/DMA/SnitchDma.py +++ b/Deeploy/Targets/Snitch/DMA/SnitchDma.py @@ -5,31 +5,41 @@ from typing import Dict, Tuple from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation, VariableBuffer -from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future, TensorGroupWaitingStrategy +from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future, PerTensorWaitingStrategy class SnitchBarrierFuture(Future): _initTemplate = NodeTemplate("") _deinitTemplate = NodeTemplate("") + _allocTemplate = NodeTemplate("") _waitTemplate = NodeTemplate("if (snrt_is_dm_core()) snrt_dma_wait_all();") # LMACAN: TODO: Add single transfer waiting class SnitchFuture(Future): - _initTemplate = NodeTemplate("uint16_t ${name};") + _initTemplate = NodeTemplate("snrt_dma_txid_t ${name} = (snrt_dma_txid_t) -1;") + _deinitTemplate = NodeTemplate("") - _waitTemplate = NodeTemplate("if (snrt_is_dm_core()) snrt_dma_wait(${name});") + + _allocTemplate = NodeTemplate("") + + _waitTemplate = NodeTemplate( + "if ( (${name} != ( (snrt_dma_txid_t) -1) ) && snrt_is_dm_core() ) snrt_dma_wait(${name});") class SnitchDma(AsyncDma): _transferTemplates = { 2: - NodeTemplate( - "if (snrt_is_dm_core()) snrt_dma_start_2d(${dest}, ${src}, ${size}, ${stride_dest}, ${stride_src}, ${repeat});" - ), + NodeTemplate(""" + if (snrt_is_dm_core()) { + ${future} = snrt_dma_start_2d(${dest}, ${src}, ${size}, ${stride_dest}, ${stride_src}, ${repeat}); + // WIESEP: Hack as otherwise the last commited DMA transaction ID can never be resolved. + snrt_dma_start_2d(${dest}, ${dest}, 1, 0, 0, 0); + } + """), } - _waitingStrategy = TensorGroupWaitingStrategy(SnitchBarrierFuture, "") + _waitingStrategy = PerTensorWaitingStrategy(SnitchFuture) def __init__(self, transferTemplates: Dict[int, NodeTemplate] = _transferTemplates) -> None: super().__init__(transferTemplates) @@ -43,7 +53,6 @@ def checkTransfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, lo def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, future: Future) -> OperatorRepresentation: - _ = future operatorRepresentation: OperatorRepresentation = { "dest": localBuffer.name if direction == "ExternalToLocal" else externalBuffer.name, "src": externalBuffer.name if direction == "ExternalToLocal" else localBuffer.name, @@ -51,5 +60,6 @@ def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBu "size": shape[1], "stride_dest": strideLoc[0] if direction == "ExternalToLocal" else strideExt[0], "stride_src": strideExt[0] if direction == "ExternalToLocal" else strideLoc[0], + "future": future.name } return operatorRepresentation diff --git a/Deeploy/TilingExtension/AsyncDma.py b/Deeploy/TilingExtension/AsyncDma.py index 63efbda17f..a2b4efe45d 100644 --- a/Deeploy/TilingExtension/AsyncDma.py +++ b/Deeploy/TilingExtension/AsyncDma.py @@ -16,6 +16,7 @@ class Future: _initTemplate: NodeTemplate + _allocTemplate: NodeTemplate _deinitTemplate: NodeTemplate _waitTemplate: NodeTemplate @@ -28,6 +29,9 @@ def _operatorRepresentation(self) -> OperatorRepresentation: def init(self) -> CodeSnippet: return CodeSnippet(self._initTemplate, self._operatorRepresentation()) + def alloc(self) -> CodeSnippet: + return CodeSnippet(self._allocTemplate, self._operatorRepresentation()) + def deinit(self) -> CodeSnippet: return CodeSnippet(self._deinitTemplate, self._operatorRepresentation()) @@ -41,25 +45,52 @@ def __init__(self, FutureCls: Type[Future]) -> None: self.FutureCls = FutureCls @abstractmethod - def getFuture(self, tensorName: str) -> Future: + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: pass class PerTensorWaitingStrategy(AsyncDmaWaitingStrategy): - def getFuture(self, tensorName: str) -> Future: - return self.FutureCls(tensorName + "_future") + def __init__(self, FutureCls: Type[Future]) -> None: + super().__init__(FutureCls) + # map (tensorName, direction) -> Future instance so the same Future + # object is returned for repeated requests for the same tensor/direction + self._futures: Dict[Tuple[str, DmaDirection], Future] = {} + + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: + key = (tensorName, direction) + if key not in self._futures: + # include direction in the future name to avoid accidental name + # collisions between directions for the same tensor + future_name = f"{tensorName}_{direction}" + self._futures[key] = self.FutureCls(future_name) + return self._futures[key] -class TensorGroupWaitingStrategy(AsyncDmaWaitingStrategy): +class DirectionWaitingStrategy(AsyncDmaWaitingStrategy): def __init__(self, FutureCls: Type[Future], asyncGroupName: str) -> None: super().__init__(FutureCls) - self.asyncGroupFuture = FutureCls(f"{asyncGroupName}_future") + self.asyncGroupName = asyncGroupName + self.asyncGroupFutures = { + "ExternalToLocal": FutureCls(asyncGroupName + "_input"), + "LocalToExternal": FutureCls(asyncGroupName + "_output") + } - def getFuture(self, tensorName: str) -> Future: + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: _ = tensorName - return self.asyncGroupFuture + return self.asyncGroupFutures[direction] + + +class BarrierWaitingStrategy(AsyncDmaWaitingStrategy): + + def __init__(self, FutureCls: Type[Future], barrierName: str) -> None: + super().__init__(FutureCls) + self.barrier = FutureCls(barrierName) + + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: + _ = tensorName, direction + return self.barrier class AsyncDma(ABC): @@ -69,8 +100,8 @@ class AsyncDma(ABC): def __init__(self, transferTemplates: Dict[int, NodeTemplate]) -> None: self._transferTemplates = transferTemplates - def getFuture(self, tensorName: str) -> Future: - return self._waitingStrategy.getFuture(tensorName) + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: + return self._waitingStrategy.getFuture(tensorName, direction) def supportedTransferRanks(self) -> Set[int]: return set(self._transferTemplates.keys()) @@ -98,16 +129,11 @@ def transfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBu template = self._transferTemplates[len(shape)] return [CodeSnippet(template, opRepr)] - def setup(self) -> List[CodeSnippet]: - return [] - - def teardown(self) -> List[CodeSnippet]: - return [] - class EmptyFuture(Future): _initTemplate = NodeTemplate("") + _allocTemplate = NodeTemplate("") _deinitTemplate = NodeTemplate("") _waitTemplate = NodeTemplate("") @@ -123,6 +149,9 @@ def __init__(self, dma: AsyncDma) -> None: def _transferTemplates(self) -> Dict[int, NodeTemplate]: return self.dma._transferTemplates + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: + return self.dma.getFuture(tensorName, direction) + def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, future: Future) -> OperatorRepresentation: @@ -131,21 +160,13 @@ def transferOpRepr(self, externalBuffer: VariableBuffer, localBuffer: VariableBu def transfer(self, ctxt: NetworkContext, externalBuffer: VariableBuffer, localBuffer: VariableBuffer, shape: Tuple[int, ...], strideExt: Tuple[int, ...], strideLoc: Tuple[int, ...], direction: DmaDirection, future: Future) -> List[CodeSnippet]: - tmpFuture = self.dma.getFuture(future.name.removesuffix("_future")) callStack = [] - callStack.append(tmpFuture.init()) - callStack.extend( - self.dma.transfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, tmpFuture)) - callStack.append(tmpFuture.wait()) - callStack.append(tmpFuture.deinit()) + dma_code = self.dma.transfer(ctxt, externalBuffer, localBuffer, shape, strideExt, strideLoc, direction, future) + callStack.append(future.alloc()) + callStack.extend(dma_code) + callStack.append(future.wait()) return callStack - def setup(self) -> List[CodeSnippet]: - return self.dma.setup() - - def teardown(self) -> List[CodeSnippet]: - return self.dma.teardown() - class AnydimAsyncDmaTransferAdapter: @@ -182,6 +203,9 @@ def __init__(self, name: str, depth: int): def __init__(self, dma: AsyncDma) -> None: self.dma = dma + def getFuture(self, tensorName: str, direction: DmaDirection) -> Future: + return self.dma.getFuture(tensorName, direction) + def nearestSupportedTransferRank(self, transfer_rank: int) -> int: sortedRanks = sorted(self.dma.supportedTransferRanks()) @@ -238,9 +262,10 @@ def transfer(self, "offset": "ext_offset" })) - callStack.extend( - self.dma.transfer(ctxt, externalBufferOffseted, localBufferOffseted, shape[-kernelRank:], - strideExt[-kernelRank:], strideLoc[-kernelRank:], direction, future)) + dma_code = self.dma.transfer(ctxt, externalBufferOffseted, localBufferOffseted, shape[-kernelRank:], + strideExt[-kernelRank:], strideLoc[-kernelRank:], direction, future) + + callStack.extend(dma_code) callStack.append(CodeSnippet(self.NestedForLoopCloseTemplate(nestedLoopDepth), {})) return callStack elif kernelRank == transferRank: diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py index 3d0e5b7018..d436d1ccc2 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/DoubleBufferingTilingCodeGeneration.py @@ -2,7 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import copy import math from typing import List, Set, Tuple @@ -12,7 +11,8 @@ from Deeploy.TilingExtension.AsyncDma import AnydimAsyncDmaTransferAdapter, AsyncDma, Future from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import dictOfArrays -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import TilingMetaInfo +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import ProfilingPrototypeMixIn, \ + PrototypeTilingMixIn, TilingMetaInfo from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint from Deeploy.TilingExtension.TilingCodegen import TilingSchedule, VariableReplacementScheme, stridesFromShape @@ -31,48 +31,89 @@ class DoubleBufferingTilingCodeGeneration(TilingCodeGeneration): # LMACAN: The brackets around ${tileIdxVar} are important to ensure correct order # of the modulo operation. Breaking case without the brackets is when we # put "TILING_I + 1" for tileIdxVar. - _chooseBufferTemplate = NodeTemplate(""" - switch((${tileIdxVar}) % 2) { - case 0: ${reference} = (${type})${buffer_0}; break; - case 1: ${reference} = (${type})${buffer_1}; break; + _switchOpen = NodeTemplate("switch((${tileIdxVar}) % ${bufferCount}) {") + _caseOpen = NodeTemplate("case ${case}:") + _caseClose = NodeTemplate("break;") + + _blockClose = NodeTemplate(""" } """) + _referenceUpdate = NodeTemplate("${reference} = (${type})${update};") + def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma): super().__init__(externalMemory, localMemory, dma, 2) - def _generateBufferChoice(self, reference: VariableBuffer, buffers: List[_ReferenceBuffer], - tileIdxVar: str) -> CodeSnippet: - assert len(buffers) == 2, f"Only double buffering supported. Received {len(buffers)} buffers." - operatorRepresentation = { - "tileIdxVar": tileIdxVar, - "reference": reference.name, - "type": reference._type.typeName, - "buffer_0": buffers[0].name, - "buffer_1": buffers[1].name, - } - template = self._chooseBufferTemplate - return CodeSnippet(template, operatorRepresentation) + def _switch(self, caseBlocks: List[List[CodeSnippet]], tileIdxVar: str) -> List[CodeSnippet]: + assert len(caseBlocks) == self.bufferCount, f"Expected {self.bufferCount} cases, got {len(caseBlocks)}`" + callStack = [CodeSnippet(self._switchOpen, {"tileIdxVar": tileIdxVar, "bufferCount": self.bufferCount})] + for i, block in enumerate(caseBlocks): + callStack.append(CodeSnippet(self._caseOpen, {"case": i})) + callStack.extend(block) + callStack.append(CodeSnippet(self._caseClose, {})) + callStack.append(CodeSnippet(self._blockClose, {})) + return callStack + + def _generateBufferChoice(self, reference: VariableBuffer, + buffers: List[_ReferenceBuffer]) -> List[List[CodeSnippet]]: + return [[ + CodeSnippet(self._referenceUpdate, { + "reference": reference.name, + "type": reference._type.typeName, + "update": buff.name + }) + ] for buff in buffers] def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - setupStatements: List[CodeSnippet] = [] - teardownStatements: List[CodeSnippet] = [] + # Double Buffering Tiling Loop Strategy + # =================================== + # - 1) Initialize all futures + # - 2) Start transfer for first input tile + # - 3) Update input reference for second tile + # - 4) for TILING_I in numTiles: + # - 4.1) Choose buffers for current tile (inputs and outputs) + # - 4.2) Input data transfer for next tile (see "4.2) Input Data Transfers") + # - 4.3) Process current tile + # - 4.4) Output data transfer for current tile (see "4.4) Output Data Transfers") + # - 5) Wait for final output tile to be ready + # - 6) Deinitialize all futures + + # 4.2) Input Data Transfers + # ----------------------------------- + # - for each input tensor: + # - 4.2.1) Wait for current input tile + # - 4.2.2) if there is a next tile: + # - 4.2.3) Choose buffers for next tile + # - 4.2.4) Start transfer for next input tile + # - 4.2.5) Update input reference for next tile + + # 4.4) Output Data Transfers + # ----------------------------------- + # - for each output tensor: + # - 4.4.1) Wait for previous output tile + # - 4.4.2) Start transfer for current output tile + # - 4.4.3) Update outut reference for next tile + setupStatements: List[CodeSnippet] = [] openLoopStatements: List[CodeSnippet] = [CodeSnippet(self._openTileLoopTemplate, {**operatorRepresentation})] - ingressDmaTransferCalls: List[CodeSnippet] = [ - CodeSnippet(self._moveTileInCheckOpenStatement, { - **operatorRepresentation, "tileIdxVar": "TILING_I+1" - }) - ] - + ingressDMAStatements: List[CodeSnippet] = [] ingressFutures: Set[Future] = set() - initialFutures: Set[Future] = set() + egressDMAStatements: List[CodeSnippet] = [] + egressFutures: Set[Future] = set() + + closeLoopStatements: List[CodeSnippet] = [CodeSnippet(self._closeTileLoopTemplate, {**operatorRepresentation})] + teardownStatements: List[CodeSnippet] = [] + + # 4.2) Input Data Transfers + # ----------------------------------- + + buffer_choices: List[List[CodeSnippet]] = [[], []] for tensorName, rectangles in dictOfArrays(tilingSchedule.inputLoadSchedule).items(): localBuffer = ctxt.lookup(operatorRepresentation[tensorName]) assert localBuffer._memoryLevel == self.localMemory @@ -98,32 +139,56 @@ def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nextLocalBufferReference = self._hoistReference(ctxt, f"{tensorName}_next", l1BuffersReferences[1]) - openLoopStatements.append(self._generateBufferChoice(localBuffer, l1BuffersReferences, "TILING_I")) - - future = self.dma.getFuture(tensorName) - ingressFutures.add(future) - - ingressDmaTransferCalls.append( - self._generateBufferChoice(nextLocalBufferReference, l1BuffersReferences, "TILING_I+1")) - ingressDmaTransferCalls.extend( - self._generateDmaTransferCalls(ctxt, tensorName, rectangles, "TILING_I+1", nextLocalBufferReference, - externalBufferRef, "ExternalToLocal", future)) + future = self.dma.getFuture(tensorName, "ExternalToLocal") + # 2) Load initial input tiles anydimAdapter = AnydimAsyncDmaTransferAdapter(self.dma) - - initialFuture = self.dma.getFuture(tensorName + "_init") - initialFutures.add(initialFuture) initialDmaTransferCalls = anydimAdapter.transfer(ctxt, externalBufferRef, localBuffer, rectangles[0].dims, stridesFromShape(externalBufferShape), stridesFromShape(rectangles[0].dims), "ExternalToLocal", - initialFuture, math.prod(externalBufferShape)) + future, math.prod(externalBufferShape)) + if future not in ingressFutures: + setupStatements.append(future.alloc()) setupStatements.extend(initialDmaTransferCalls) - setupStatements.append(initialFuture.wait()) + # 4.1) Choose buffers for current tile (inputs and outputs) + _buffer_choice = self._generateBufferChoice(localBuffer, l1BuffersReferences) + for i in range(len(buffer_choices)): + buffer_choices[i].extend(_buffer_choice[i]) + + # 4.2.1) Wait for current input tile + ingressDMAStatements.append(CodeSnippet(self._lineComment, {"comment": "Wait for current input tile"})) + + if future not in ingressFutures: + ingressDMAStatements.append(future.wait()) + + # 4.2.2) if there is a next tile: + ingressDMAStatements.append( + CodeSnippet(self._moveTileInCheckOpenStatement, { + **operatorRepresentation, "tileIdxVar": "TILING_I+1" + })) + + # 4.2.3) Choose buffers for next tile + ingressDMAStatements += self._switch( + self._generateBufferChoice(nextLocalBufferReference, l1BuffersReferences), "TILING_I+1") + + # 4.2.4) Start transfer for next input tile + ingressDMAStatements.append(CodeSnippet(self._lineComment, {"comment": "Transfer next input tile"})) + + # Allocate the future for the next transfer + if future not in ingressFutures: + ingressDMAStatements.append(future.alloc()) + + ingressDMAStatements.extend( + self._generateDmaTransferCalls(ctxt, tensorName, rectangles, "TILING_I+1", nextLocalBufferReference, + externalBufferRef, "ExternalToLocal", future)) + # 4.2.5) Update external reference for next til referenceUpdate = self._generateExternalReferenceUpdate(ctxt, tensorName, rectangles, "TILING_I+1", externalBufferRef) if referenceUpdate is not None: - ingressDmaTransferCalls.append(referenceUpdate) + ingressDMAStatements.append(referenceUpdate) + + # 3) Update input reference for second tile initialReferenceUpdate = CodeSnippet(referenceUpdate.template, operatorRepresentation = { **referenceUpdate.operatorRepresentation, @@ -131,12 +196,14 @@ def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, }) setupStatements.append(initialReferenceUpdate) - ingressDmaTransferCalls.append(CodeSnippet(self._moveTileInCheckCloseStatement, {})) - ingressDmaWaitStatements = [f.wait() for f in ingressFutures] + # Close the "if there is a next tile" block + ingressDMAStatements.append(CodeSnippet(self._moveTileInCheckCloseStatement, {})) - egressDmaTransferCalls: List[CodeSnippet] = [] - egressFutures: Set[Future] = set() + # Add future to the set to prevent double wait/allocation + ingressFutures.add(future) + # 4.4) Output Data Transfers + # ----------------------------------- for tensorName, rectangles in dictOfArrays(tilingSchedule.outputLoadSchedule).items(): localBuffer = ctxt.lookup(operatorRepresentation[tensorName]) assert localBuffer._memoryLevel == self.localMemory @@ -160,28 +227,54 @@ def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, tensorMemoryConstraint = nodeMemoryConstraint.outputTensorMemoryConstraints[externalBuffer.name] l1BuffersReferences = self._hoistMultibufferReferences(ctxt, localBuffer, tensorMemoryConstraint) - openLoopStatements.append(self._generateBufferChoice(localBuffer, l1BuffersReferences, "TILING_I")) + # 4.1) Choose buffers for current tile (inputs and outputs) + _buffer_choice = self._generateBufferChoice(localBuffer, l1BuffersReferences) + for i in range(len(buffer_choices)): + buffer_choices[i].extend(_buffer_choice[i]) - future = self.dma.getFuture(tensorName) - egressFutures.add(future) + # 4.4.1) Wait for previous output tile + future = self.dma.getFuture(tensorName, "LocalToExternal") + + egressDMAStatements.append(CodeSnippet(self._lineComment, {"comment": "Wait for previous output tile"})) + if future not in egressFutures: + egressDMAStatements.append(future.wait()) + + # 4.4.2) Start transfer for current output tile dmaTransferCalls = self._generateDmaTransferCalls(ctxt, tensorName, rectangles, "TILING_I", localBuffer, externalBufferRef, "LocalToExternal", future) - egressDmaTransferCalls.extend(dmaTransferCalls) + egressDMAStatements.append(CodeSnippet(self._lineComment, {"comment": "Transfer current output tile"})) + # Allocate the future for the next transfer + if future not in egressFutures: + egressDMAStatements.append(future.alloc()) + + egressDMAStatements.extend(dmaTransferCalls) + + # 4.4.3) Update outut reference for next tile referenceUpdate = self._generateExternalReferenceUpdate(ctxt, tensorName, rectangles, "TILING_I", externalBufferRef) if referenceUpdate is not None: - egressDmaTransferCalls.append(referenceUpdate) + egressDMAStatements.append(referenceUpdate) + + # Add future to the set to prevent double wait/allocation + egressFutures.add(future) + + # 4.2. + openLoopStatements += self._switch(buffer_choices, "TILING_I") - egressDmaWaitStatements = [f.wait() for f in egressFutures] + # 1. Initialize all futures + setupStatements = [f.init() for f in ingressFutures | egressFutures] + setupStatements + setupStatements = [CodeSnippet(self._lineComment, {"comment": "Initialize DMA future"})] + setupStatements + # 5. Wait for final output tile to be ready + teardownStatements.append(CodeSnippet(self._lineComment, {"comment": "Wait for final output tile"})) teardownStatements.extend([f.wait() for f in egressFutures]) - setupStatements = [f.init() for f in ingressFutures | initialFutures | egressFutures] + setupStatements - teardownStatements.extend(f.deinit() for f in ingressFutures | initialFutures | egressFutures) + # 6. Deinitialize all futures - closeLoopStatements = [CodeSnippet(self._closeTileLoopTemplate, {**operatorRepresentation})] + teardownStatements.append(CodeSnippet(self._lineComment, {"comment": "Deinitialize DMA future"})) + teardownStatements.extend(f.deinit() for f in ingressFutures | egressFutures) metaInfo = TilingMetaInfo( nodeName = operatorRepresentation['nodeName'] + f"_{self.externalMemory}", @@ -195,34 +288,83 @@ def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, # which is hardcoded by the value "L1". Change this to be memory level agnostic. kernelLevelTiling = self.localMemory == "L1") - executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDmaTransferCalls, - ingressDmaWaitStatements, [], egressDmaTransferCalls, - egressDmaWaitStatements, [], [], openLoopStatements, - closeLoopStatements, setupStatements, teardownStatements) + executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMAStatements, egressDMAStatements, + openLoopStatements, closeLoopStatements, setupStatements, + teardownStatements) return ctxt, executionBlock, True - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == self.bufferCount: - return ctxt, executionBlock, False - - numTiles, tileIdxPtr = self._hoistTileNumAndIdxPtr(ctxt, tilingSchedules) - operatorRepresentation["numTiles"] = numTiles.name - operatorRepresentation["tileIdxPtr"] = tileIdxPtr.name - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) +class ProfilingDoubleBufferingTilingMixIn(PrototypeTilingMixIn, ProfilingPrototypeMixIn): + + @classmethod + def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, + setupStatements: List[CodeSnippet], + teardownStatements: List[CodeSnippet]) -> ExecutionBlock: + + nodeName = metaInfo.nodeName + totalNumTiles = metaInfo.totalNumTiles + + executionBlock.addLeft(cls._measureCycles, { + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": 0 + }) + + executionBlock = cls.measurementArrayDeclaration(executionBlock, metaInfo, bufferingStr = "DB") + + executionBlock = super().generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, + teardownStatements) + executionBlock.addRight(cls._measureCycles, { + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": totalNumTiles - 1 + }) + + executionBlock = cls.injectPrintCycleDiff(executionBlock, metaInfo) + + return executionBlock + + @classmethod + def generateLoopCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, + openLoopStatements: List[CodeSnippet], ingressDMAStatements: List[CodeSnippet], + egressDMAStatements: List[CodeSnippet], + closeLoopStatements: List[CodeSnippet]) -> ExecutionBlock: + + nodeName = metaInfo.nodeName + tileIdxVar = metaInfo.tileIdxVar + + _openLoopStatements = [openLoopStatements[0]] + _openLoopStatements.append(CodeSnippet(cls._measureConditionSetup, {"cond": f"{tileIdxVar} > 0"})) + _openLoopStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar + })) + _openLoopStatements.append(CodeSnippet(cls._measureConditionEnd, {})) + _openLoopStatements += openLoopStatements[1:] + + _ingressDMAStatements = [] + _ingressDMAStatements += ingressDMAStatements + _ingressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar + })) + + executionBlock = cls.kernelProfilingWrap(executionBlock, metaInfo) + + _egressDMAStatements = [] + _egressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_egress_dma_wait_start_measurements", + "tileIdxVar": f"{tileIdxVar}" + })) + _egressDMAStatements += egressDMAStatements + _egressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": f"{tileIdxVar}" + })) + + executionBlock = super().generateLoopCode(executionBlock, metaInfo, _openLoopStatements, _ingressDMAStatements, + _egressDMAStatements, closeLoopStatements) + return executionBlock diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py index bc863e8d22..268aa8fca8 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/SingleBufferingTilingCodeGeneration.py @@ -2,7 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import copy from typing import Dict, List, Set, Tuple from Deeploy.AbstractDataTypes import VoidType @@ -11,7 +10,8 @@ from Deeploy.TilingExtension.AsyncDma import AsyncDma, DmaDirection, Future from Deeploy.TilingExtension.CodeTransformationPasses.TilingCodeGeneration import TilingCodeGeneration from Deeploy.TilingExtension.CodeTransformationPasses.TilingHoistingMixIn import dictOfArrays -from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import TilingMetaInfo +from Deeploy.TilingExtension.CodeTransformationPasses.TilingPrototypes import ProfilingPrototypeMixIn, \ + PrototypeTilingMixIn, TilingMetaInfo from Deeploy.TilingExtension.MemoryConstraints import NodeMemoryConstraint, TensorMemoryConstraint from Deeploy.TilingExtension.TilingCodegen import HyperRectangle, TilingSchedule, VariableReplacementScheme @@ -27,7 +27,6 @@ def _generateTransferScheduleCalls( TensorMemoryConstraint], tileIdxVar: str, direction: DmaDirection) -> Tuple[NetworkContext, List[CodeSnippet], Set[Future]]: callStack: List[CodeSnippet] = [] - referenceUpdates: List[CodeSnippet] = [] futures: Set[Future] = set() for tensorName, rectangles in dictOfArrays(transferSchedule).items(): @@ -50,8 +49,11 @@ def _generateTransferScheduleCalls( shape = externalBufferShape, override_type = VoidType) - future = self.dma.getFuture(tensorName) - futures.add(future) + future = self.dma.getFuture(tensorName, direction) + + # Allocate a future for this transfer + if future not in futures: + callStack.append(future.alloc()) callStack.extend( self._generateDmaTransferCalls(ctxt, tensorName, rectangles, tileIdxVar, localBuffer, externalBufferRef, @@ -62,29 +64,54 @@ def _generateTransferScheduleCalls( if referenceUpdate is not None: callStack.append(referenceUpdate) + futures.add(future) + return ctxt, callStack, futures def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, variableReplacement: VariableReplacementScheme, operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - ctxt, ingressDmaTransferCalls, ingressFutures = self._generateTransferScheduleCalls( + + # Single Buffering Tiling Loop Strategy + # =================================== + # - 1) Initialize all futures + # - 2) for TILING_I in numTiles: + # - 2.1) Input data transfer for current tile (see "4.2) Input Data Transfers") + # - 2.2) Process current tile + # - 2.3) Output data transfer for current tile (see "4.4) Output Data Transfers") + # - 3) Deinitialize all futures + + # 2) for TILING_I in numTiles: + openLoopStatements = [CodeSnippet(self._openTileLoopTemplate, {**operatorRepresentation})] + + # 2.2) Input data transfer for current tile + ctxt, ingressDMAStatements, ingressFutures = self._generateTransferScheduleCalls( ctxt, operatorRepresentation, tilingSchedule.inputLoadSchedule, nodeMemoryConstraint.inputTensorMemoryConstraints, "TILING_I", "ExternalToLocal") - ctxt, egressDmaTransferCalls, egressFutures = self._generateTransferScheduleCalls( + + ingressDMAStatements = [CodeSnippet(self._lineComment, {"comment": "Transfer input tiles"}) + ] + ingressDMAStatements + ingressDMAStatements += [CodeSnippet(self._lineComment, {"comment": "Wait for input tiles"})] + ingressDMAStatements += [future.wait() for future in ingressFutures] + + # 2.4) Output data transfer for current tile + ctxt, egressDMAStatements, egressFutures = self._generateTransferScheduleCalls( ctxt, operatorRepresentation, tilingSchedule.outputLoadSchedule, nodeMemoryConstraint.outputTensorMemoryConstraints, "TILING_I", "LocalToExternal") + egressDMAStatements = [CodeSnippet(self._lineComment, {"comment": "Transfer output tiles"}) + ] + egressDMAStatements + egressDMAStatements += [CodeSnippet(self._lineComment, {"comment": "Wait for output tiles"})] + egressDMAStatements += [future.wait() for future in egressFutures] - ingressDmaWaitStatements = [future.wait() for future in ingressFutures] - egressDmaWaitStatements = [future.wait() for future in egressFutures] - - setupStatements = self.dma.setup() - setupStatements += [f.init() for f in ingressFutures | egressFutures] + # 1) Initialize all futures + setupStatements = [CodeSnippet(self._lineComment, {"comment": "Initialize DMA futures"})] + setupStatements.extend([f.init() for f in ingressFutures | egressFutures]) - teardownStatements = self.dma.teardown() - teardownStatements.extend(f.deinit() for f in ingressFutures | egressFutures) + # 3) Deinitialize all futures + teardownStatements = [CodeSnippet(self._lineComment, {"comment": "Deinitialize DMA futures"})] + teardownStatements.extend([f.deinit() for f in ingressFutures | egressFutures]) - openLoopStatements = [CodeSnippet(self._openTileLoopTemplate, {**operatorRepresentation})] closeLoopStatements = [CodeSnippet(self._closeTileLoopTemplate, {**operatorRepresentation})] metaInfo = TilingMetaInfo( @@ -99,34 +126,69 @@ def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, # which is hardcoded by the value "L1". Change this to be memory level agnostic. kernelLevelTiling = self.localMemory == "L1") - executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDmaTransferCalls, - ingressDmaWaitStatements, [], egressDmaTransferCalls, - egressDmaWaitStatements, [], [], openLoopStatements, - closeLoopStatements, setupStatements, teardownStatements) + executionBlock = self.generateAllTilingCode(executionBlock, metaInfo, ingressDMAStatements, egressDMAStatements, + openLoopStatements, closeLoopStatements, setupStatements, + teardownStatements) return ctxt, executionBlock, True - def generateTilingLoop( - self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, - tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, - operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - - flatTilingSchedule = copy.copy(tilingSchedules[0]) - for tilingSchedule in tilingSchedules[1:]: - flatTilingSchedule += tilingSchedule - - offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) - - if len(offsetLists) == 0: - return ctxt, executionBlock, False - - for offsetList in offsetLists: - if not len(offsetList) == self.bufferCount: - return ctxt, executionBlock, False - - numTiles, tileIdxPtr = self._hoistTileNumAndIdxPtr(ctxt, tilingSchedules) - operatorRepresentation["numTiles"] = numTiles.name - operatorRepresentation["tileIdxPtr"] = tileIdxPtr.name - return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, - operatorRepresentation) +class ProfilingSingleBufferingTilingMixIn(PrototypeTilingMixIn, ProfilingPrototypeMixIn): + + @classmethod + def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, + setupStatements: List[CodeSnippet], + teardownStatements: List[CodeSnippet]) -> ExecutionBlock: + + executionBlock = super().generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, + teardownStatements) + + executionBlock = cls.measurementArrayDeclaration(executionBlock, metaInfo, bufferingStr = "SB") + + executionBlock = cls.injectPrintCycleDiff(executionBlock, metaInfo) + + return executionBlock + + @classmethod + def generateLoopCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, + openLoopStatements: List[CodeSnippet], ingressDMAStatements: List[CodeSnippet], + egressDMAStatements: List[CodeSnippet], + closeLoopStatements: List[CodeSnippet]) -> ExecutionBlock: + + nodeName = metaInfo.nodeName + tileIdxVar = metaInfo.tileIdxVar + + _openLoopStatements = [openLoopStatements[0]] + _openLoopStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar + })) + _openLoopStatements += openLoopStatements[1:] + + _ingressDMAStatements = [] + _ingressDMAStatements += ingressDMAStatements + _ingressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar + })) + + executionBlock = cls.kernelProfilingWrap(executionBlock, metaInfo) + + _egressDMAStatements = [] + _egressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_egress_dma_wait_start_measurements", + "tileIdxVar": tileIdxVar + })) + _egressDMAStatements += egressDMAStatements + _egressDMAStatements.append( + CodeSnippet(cls._measureCycles, { + "measurements": f"{nodeName}_egress_dma_wait_end_measurements", + "tileIdxVar": tileIdxVar + })) + + executionBlock = super().generateLoopCode(executionBlock, metaInfo, _openLoopStatements, _ingressDMAStatements, + _egressDMAStatements, closeLoopStatements) + return executionBlock diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py index 0db3109aea..a796c52f7f 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingCodeGeneration.py @@ -40,6 +40,8 @@ def transposeListOfLists(listOfLists: List[List[T]]) -> List[List[T]]: class TilingCodeGeneration(CodeTransformationPass, IntrospectiveCodeTransformationMixIn, PrototypeTilingMixIn, TilingHoistingMixIn): + _lineComment = NodeTemplate("\n// ${comment}") + _relativeOffsetReferenceUpdateTemplate = NodeTemplate(""" // UPDATE VARIABLE ${reference} ${reference} += ${relativeOffset}; @@ -62,12 +64,36 @@ class TilingCodeGeneration(CodeTransformationPass, IntrospectiveCodeTransformati """) @abstractmethod + def _tilingLoop(self, ctxt: NetworkContext, executionBlock: ExecutionBlock, + nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedule: TilingSchedule, + variableReplacement: VariableReplacementScheme, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: + pass + def generateTilingLoop( self, ctxt: NetworkContext, executionBlock: ExecutionBlock, nodeMemoryConstraint: NodeMemoryConstraint, tilingSchedules: List[TilingSchedule], variableReplacement: VariableReplacementScheme, operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, ExecutionBlock, bool]: - return ctxt, executionBlock, False + flatTilingSchedule = copy.copy(tilingSchedules[0]) + for tilingSchedule in tilingSchedules[1:]: + flatTilingSchedule += tilingSchedule + + offsetLists = list({**flatTilingSchedule.inputBaseOffsets, **flatTilingSchedule.outputBaseOffsets}.values()) + + if len(offsetLists) == 0: + return ctxt, executionBlock, False + + for offsetList in offsetLists: + if not len(offsetList) == self.bufferCount: + return ctxt, executionBlock, False + + numTiles, tileIdxPtr = self._hoistTileNumAndIdxPtr(ctxt, tilingSchedules) + operatorRepresentation["numTiles"] = numTiles.name + operatorRepresentation["tileIdxPtr"] = tileIdxPtr.name + + return self._tilingLoop(ctxt, executionBlock, nodeMemoryConstraint, flatTilingSchedule, variableReplacement, + operatorRepresentation) def __init__(self, externalMemory: str, localMemory: str, dma: AsyncDma, bufferCount: int): self.externalMemory = externalMemory @@ -102,8 +128,9 @@ def _generateDmaTransferCalls(self, ctxt: NetworkContext, tensorName: str, trans initSnippets = anydimAdapter.transfer(ctxt, externalBuffer, localBuffer, transfers[0].dims, stridesFromShape(externalBuffer.shape), stridesFromShape(transfers[0].dims), direction, future, - math.prod(externalBuffer.shape)) + math.prod(externalBuffer.shape,)) + # Add allocation snippets templates = [snippet.template for snippet in initSnippets] opReprUpdates = [[] for _ in range(len(initSnippets))] diff --git a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py index 1a875b626b..2f6c1e9590 100644 --- a/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py +++ b/Deeploy/TilingExtension/CodeTransformationPasses/TilingPrototypes.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from abc import ABC, abstractmethod +from abc import ABC from dataclasses import dataclass from typing import List, Literal @@ -20,52 +20,12 @@ class TilingMetaInfo: kernelLevelTiling: bool -_CodeSegmentType = List[CodeSnippet] - -_measureCycles = NodeTemplate(""" -${measurements}[${tileIdxVar}] = getCycles(); -""") - -_measurementArrayDeclaration = NodeTemplate(""" -uint32_t ${measurements}[${totalNumTiles}]; -""") - -_stringDeclaration = NodeTemplate(""" -const static char ${name}[] = "${string}"; -""") - -_measureConditionSetup = NodeTemplate(""" -if(${cond}){ -""") - -_measureConditionEnd = NodeTemplate(""" -} -""") - -_printLoopSetup = NodeTemplate(""" -StopTimer(); -for (int ${profileIdxVar} = ((*${tileIdxPtr} > 0) ? ${numTiles}[(*${tileIdxPtr} - 1)] : 0); - ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; - ${profileIdxVar}++){ -""") - -_printCycleDifference = NodeTemplate(r""" -printf("%s%u] %s%u%s", ${prefixStr}, ${profileIdxVar}, "${flavorStr}", \ -${measurementsEnd}[${profileIdxVar}] - ${measurementsStart}[${profileIdxVar}], ${suffixStr}); -""") - -_printLoopTeardown = NodeTemplate(""" -} -StartTimer(); -""") - - class PrototypeTilingMixIn(ABC): @classmethod def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - setupStatements: _CodeSegmentType, - teardownStatements: _CodeSegmentType) -> ExecutionBlock: + setupStatements: List[CodeSnippet], + teardownStatements: List[CodeSnippet]) -> ExecutionBlock: for transaction in reversed(setupStatements): executionBlock.addLeft(transaction.template, transaction.operatorRepresentation) @@ -77,53 +37,70 @@ def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: @classmethod def generateLoopCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - openLoopStatements: _CodeSegmentType, closeLoopStatements: _CodeSegmentType) -> ExecutionBlock: + openLoopStatements: List[CodeSnippet], ingressDMAStatements: List[CodeSnippet], + egressDMAStatements: List[CodeSnippet], + closeLoopStatements: List[CodeSnippet]) -> ExecutionBlock: - for transaction in reversed(openLoopStatements): + for transaction in reversed(openLoopStatements + ingressDMAStatements): executionBlock.addLeft(transaction.template, transaction.operatorRepresentation) - for transaction in closeLoopStatements: + for transaction in egressDMAStatements + closeLoopStatements: executionBlock.addRight(transaction.template, transaction.operatorRepresentation) return executionBlock @classmethod def generateAllTilingCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType, openLoopStatements: _CodeSegmentType, - closeLoopStatements: _CodeSegmentType, setupStatements: _CodeSegmentType, - teardownStatements: _CodeSegmentType) -> ExecutionBlock: - - if not hasattr(cls, "generateInnerCode"): - raise Exception("You need to mix in a code gen strategy!") - - newExecutionBlock = cls.generateInnerCode(executionBlock, metaInfo, ingressDMATransferCalls, - ingressDMAWaitStatements, ingressDMAUpdates, egressDMATransferCalls, - egressDMAWaitStatements, egressDMAUpdates, variableUpdates) + ingressDMAStatements: List[CodeSnippet], egressDMAStatements: List[CodeSnippet], + openLoopStatements: List[CodeSnippet], closeLoopStatements: List[CodeSnippet], + setupStatements: List[CodeSnippet], + teardownStatements: List[CodeSnippet]) -> ExecutionBlock: - newExecutionBlock = cls.generateLoopCode(newExecutionBlock, metaInfo, openLoopStatements, closeLoopStatements) + executionBlock = cls.generateLoopCode(executionBlock, metaInfo, openLoopStatements, ingressDMAStatements, + egressDMAStatements, closeLoopStatements) - newExecutionBlock = cls.generateSetupAndTeardownCode(newExecutionBlock, metaInfo, setupStatements, - teardownStatements) - - return newExecutionBlock - - -class TilingCodeGenMixin(ABC): - - @abstractmethod - def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType) -> ExecutionBlock: + executionBlock = cls.generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, teardownStatements) return executionBlock class ProfilingPrototypeMixIn(ABC): + _measureCycles = NodeTemplate(""" + ${measurements}[${tileIdxVar}] = getCycles(); + """) + + _measurementArrayDeclaration = NodeTemplate(""" + uint32_t ${measurements}[${totalNumTiles}]; + """) + + _stringDeclaration = NodeTemplate(""" + const static char ${name}[] = "${string}"; + """) + + _printLoopSetup = NodeTemplate(""" + StopTimer(); + for (int ${profileIdxVar} = ((*${tileIdxPtr} > 0) ? ${numTiles}[(*${tileIdxPtr} - 1)] : 0); + ${profileIdxVar} < ${numTiles}[*${tileIdxPtr}]; + ${profileIdxVar}++){ + """) + + _printCycleDifference = NodeTemplate(r""" + printf("%s%u] %s%u%s", ${prefixStr}, ${profileIdxVar}, "${flavorStr}", \ + ${measurementsEnd}[${profileIdxVar}] - ${measurementsStart}[${profileIdxVar}], ${suffixStr}); + """) + + _printLoopTeardown = NodeTemplate(""" + } + StartTimer(); + """) + + _measureConditionSetup = NodeTemplate(""" + if(${cond}){ + """) + + _measureConditionEnd = NodeTemplate(""" + } + """) @classmethod def measurementArrayDeclaration(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, @@ -142,17 +119,17 @@ def measurementArrayDeclaration(cls, executionBlock: ExecutionBlock, metaInfo: T measurementsList = ["kernel_start", "kernel_end"] + measurementsList for measurements in measurementsList: - executionBlock.addLeft(_measurementArrayDeclaration, { + executionBlock.addLeft(cls._measurementArrayDeclaration, { "measurements": f"{nodeName}_{measurements}_measurements", "totalNumTiles": totalNumTiles }) - executionBlock.addLeft(_stringDeclaration, { + executionBlock.addLeft(cls._stringDeclaration, { "name": f"{nodeName}_prefix", "string": f"[{nodeName}][{bufferingStr}][{nodeOps} ops][Tile ", }) - executionBlock.addLeft(_stringDeclaration, { + executionBlock.addLeft(cls._stringDeclaration, { "name": f"{nodeName}_suffix", "string": " cycles \\n", }) @@ -165,10 +142,9 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe numTiles = metaInfo.numTiles nodeName = metaInfo.nodeName tileIdxPtr = metaInfo.tileIdxPtr - totalNumTiles = metaInfo.totalNumTiles profileIdxVar = "PROFILING_I" - executionBlock.addRight(_printLoopSetup, { + executionBlock.addRight(cls._printLoopSetup, { "numTiles": numTiles, "nodeName": nodeName, "profileIdxVar": profileIdxVar, @@ -176,7 +152,7 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe }) executionBlock.addRight( - _printCycleDifference, { + cls._printCycleDifference, { "prefixStr": f"{nodeName}_prefix", "suffixStr": f"{nodeName}_suffix", "flavorStr": "Input DMA took ", @@ -187,7 +163,7 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe if metaInfo.kernelLevelTiling: executionBlock.addRight( - _printCycleDifference, { + cls._printCycleDifference, { "prefixStr": f"{nodeName}_prefix", "suffixStr": f"{nodeName}_suffix", "flavorStr": "Kernel took ", @@ -197,7 +173,7 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe }) executionBlock.addRight( - _printCycleDifference, { + cls._printCycleDifference, { "prefixStr": f"{nodeName}_prefix", "suffixStr": f"{nodeName}_suffix", "flavorStr": "Output DMA took ", @@ -206,7 +182,7 @@ def injectPrintCycleDiff(cls, executionBlock: ExecutionBlock, metaInfo: TilingMe "profileIdxVar": profileIdxVar, }) - executionBlock.addRight(_printLoopTeardown, {}) + executionBlock.addRight(cls._printLoopTeardown, {}) return executionBlock @@ -216,218 +192,13 @@ def kernelProfilingWrap(cls, executionBlock: ExecutionBlock, metaInfo: TilingMet tileIdxVar = metaInfo.tileIdxVar if metaInfo.kernelLevelTiling: - executionBlock.addLeft(_measureCycles, { + executionBlock.addLeft(cls._measureCycles, { "measurements": f"{nodeName}_kernel_start_measurements", "tileIdxVar": tileIdxVar }) - executionBlock.addRight(_measureCycles, { + executionBlock.addRight(cls._measureCycles, { "measurements": f"{nodeName}_kernel_end_measurements", "tileIdxVar": tileIdxVar }) return executionBlock - - -class SingleBufferingTilingMixIn(PrototypeTilingMixIn, TilingCodeGenMixin): - - @classmethod - def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType) -> ExecutionBlock: - - # Structure: - # Update DMA Structs - # Transfer in tiles (async) - # Update tile variables - # Wait for tiles - - # Kernel execution - - # Update DMA Structs - # Transfer out tiles (async) - # Wait for out transfers - - for transaction in reversed(ingressDMAUpdates + ingressDMATransferCalls + variableUpdates + - ingressDMAWaitStatements): - executionBlock.addLeft(transaction.template, transaction.operatorRepresentation) - - for transaction in (egressDMAUpdates + egressDMATransferCalls + egressDMAWaitStatements): - executionBlock.addRight(transaction.template, transaction.operatorRepresentation) - - return executionBlock - - -class ProfilingSingleBufferingTilingMixIn(SingleBufferingTilingMixIn, ProfilingPrototypeMixIn): - - @classmethod - def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - setupStatements: _CodeSegmentType, - teardownStatements: _CodeSegmentType) -> ExecutionBlock: - - executionBlock = super().generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, - teardownStatements) - - executionBlock = cls.measurementArrayDeclaration(executionBlock, metaInfo, bufferingStr = "SB") - - executionBlock = cls.injectPrintCycleDiff(executionBlock, metaInfo) - - return executionBlock - - @classmethod - def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType) -> ExecutionBlock: - - nodeName = metaInfo.nodeName - tileIdxVar = metaInfo.tileIdxVar - - executionBlock = cls.kernelProfilingWrap(executionBlock, metaInfo) - - _ingressDMAWaitStatements = [] - _ingressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", - "tileIdxVar": tileIdxVar - })) - _ingressDMAWaitStatements += ingressDMAWaitStatements - _ingressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", - "tileIdxVar": tileIdxVar - })) - - _egressDMAWaitStatements = [] - _egressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_start_measurements", - "tileIdxVar": tileIdxVar - })) - _egressDMAWaitStatements += egressDMAWaitStatements - _egressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_end_measurements", - "tileIdxVar": tileIdxVar - })) - - executionBlock = super().generateInnerCode(executionBlock, metaInfo, ingressDMATransferCalls, - _ingressDMAWaitStatements, ingressDMAUpdates, egressDMATransferCalls, - _egressDMAWaitStatements, egressDMAUpdates, variableUpdates) - - return executionBlock - - -class DoubleBufferingTilingMixIn(PrototypeTilingMixIn, TilingCodeGenMixin): - - @classmethod - def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType) -> ExecutionBlock: - - # Structure: - - # Update input DMA Structs - # Update tile variables - # Wait for current input tiles - # Transfer in next input tiles (async) - # Update output DMA Structs - # Wait for current output tiles - - # Kernel execution - - # Transfer out tiles (async) - - for transaction in reversed(ingressDMAWaitStatements + ingressDMAUpdates + ingressDMATransferCalls + - variableUpdates + egressDMAWaitStatements + egressDMAUpdates): - executionBlock.addLeft(transaction.template, transaction.operatorRepresentation) - - for transaction in egressDMATransferCalls: - executionBlock.addRight(transaction.template, transaction.operatorRepresentation) - - return executionBlock - - -class ProfilingDoubleBufferingTilingMixIn(DoubleBufferingTilingMixIn, ProfilingPrototypeMixIn): - - @classmethod - def generateSetupAndTeardownCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - setupStatements: _CodeSegmentType, - teardownStatements: _CodeSegmentType) -> ExecutionBlock: - - nodeName = metaInfo.nodeName - totalNumTiles = metaInfo.totalNumTiles - - executionBlock.addLeft(_measureCycles, { - "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", - "tileIdxVar": 0 - }) - - executionBlock = cls.measurementArrayDeclaration(executionBlock, metaInfo, bufferingStr = "DB") - - executionBlock.addRight(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_start_measurements", - "tileIdxVar": totalNumTiles - 1 - }) - executionBlock = super().generateSetupAndTeardownCode(executionBlock, metaInfo, setupStatements, - teardownStatements) - executionBlock.addRight(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_end_measurements", - "tileIdxVar": totalNumTiles - 1 - }) - - executionBlock = cls.injectPrintCycleDiff(executionBlock, metaInfo) - - return executionBlock - - @classmethod - def generateInnerCode(cls, executionBlock: ExecutionBlock, metaInfo: TilingMetaInfo, - ingressDMATransferCalls: _CodeSegmentType, ingressDMAWaitStatements: _CodeSegmentType, - ingressDMAUpdates: _CodeSegmentType, egressDMATransferCalls: _CodeSegmentType, - egressDMAWaitStatements: _CodeSegmentType, egressDMAUpdates: _CodeSegmentType, - variableUpdates: _CodeSegmentType) -> ExecutionBlock: - - nodeName = metaInfo.nodeName - tileIdxVar = metaInfo.tileIdxVar - - executionBlock = cls.kernelProfilingWrap(executionBlock, metaInfo) - - _ingressDMAWaitStatements = [] - _ingressDMAWaitStatements.append(CodeSnippet(_measureConditionSetup, {"cond": f"{tileIdxVar} > 0"})) - _ingressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_ingress_dma_wait_start_measurements", - "tileIdxVar": tileIdxVar - })) - _ingressDMAWaitStatements.append(CodeSnippet(_measureConditionEnd, {})) - _ingressDMAWaitStatements += ingressDMAWaitStatements - _ingressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_ingress_dma_wait_end_measurements", - "tileIdxVar": tileIdxVar - })) - - _egressDMAWaitStatements = [] - _egressDMAWaitStatements.append(CodeSnippet(_measureConditionSetup, {"cond": f"{tileIdxVar} > 0"})) - _egressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_start_measurements", - "tileIdxVar": f"{tileIdxVar} - 1" - })) - _egressDMAWaitStatements += egressDMAWaitStatements - _egressDMAWaitStatements.append( - CodeSnippet(_measureCycles, { - "measurements": f"{nodeName}_egress_dma_wait_end_measurements", - "tileIdxVar": f"{tileIdxVar} - 1" - })) - _egressDMAWaitStatements.append(CodeSnippet(_measureConditionEnd, {})) - - executionBlock = super().generateInnerCode(executionBlock, metaInfo, ingressDMATransferCalls, - _ingressDMAWaitStatements, ingressDMAUpdates, egressDMATransferCalls, - _egressDMAWaitStatements, egressDMAUpdates, variableUpdates) - - return executionBlock diff --git a/DeeployTest/Platforms/Snitch/main.c b/DeeployTest/Platforms/Snitch/main.c index 89e6551436..a7251f3844 100644 --- a/DeeployTest/Platforms/Snitch/main.c +++ b/DeeployTest/Platforms/Snitch/main.c @@ -77,23 +77,20 @@ int main(void) { snrt_cluster_hw_barrier(); -#if !defined(BANSHEE_SIMULATION) && !defined(GVSOC_SIMULATION) - if (snrt_is_dm_core()) { - ResetTimer(); - StartTimer(); - } -#endif // BANSHEE_SIMULATION and GVSOC_SIMULATION - + ResetTimer(); + StartTimer(); + snrt_cluster_hw_barrier(); RunNetwork(compute_core_id, num_compute_cores); uint32_t runtimeCycles = 0; -#if !defined(BANSHEE_SIMULATION) && !defined(GVSOC_SIMULATION) if (snrt_is_dm_core()) { runtimeCycles = getCycles(); +#if !defined(BANSHEE_SIMULATION) && !defined(GVSOC_SIMULATION) DUMP(runtimeCycles); - StopTimer(); - } #endif // BANSHEE_SIMULATION and GVSOC_SIMULATION + } + + StopTimer(); snrt_cluster_hw_barrier(); diff --git a/TargetLibraries/PULPOpen/inc/mchan_v6.h b/TargetLibraries/PULPOpen/inc/mchan_v6.h index bf7cfc1ddb..34a42d882e 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_v6.h +++ b/TargetLibraries/PULPOpen/inc/mchan_v6.h @@ -7,6 +7,8 @@ #ifndef __MCHAN_V6_H__ #define __MCHAN_V6_H__ +#include "assert.h" + // Requires to have MCHAN_BASE_ADDR, MCHAN_EVENT defined outside of header #ifndef MCHAN_BASE_ADDR #error "[mchan_v6.h] MCHAN_BASE_ADDR not defined!" @@ -34,6 +36,7 @@ #include "pmsis.h" #define MCHAN_TRANSFER_LEN_SIZE (16) +#define MCHAN_CHANNEL_ID_MAX (15) #define MCHAN_CMD_FLAG_DIRECTION_LOC2EXT (0 << (MCHAN_TRANSFER_LEN_SIZE + 0)) #define MCHAN_CMD_FLAG_DIRECTION_EXT2LOC (1 << (MCHAN_TRANSFER_LEN_SIZE + 0)) @@ -68,17 +71,17 @@ static void mchan_transfer_2d_ext_strided(uint32_t cmd, void *loc, void *ext, static uint32_t mchan_channel_alloc() { return *cmd_ptr; } static void mchan_channel_free(uint32_t channel_id) { - // TODO: assert channel_id is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); *status_ptr = 1 << channel_id; } static uint32_t mchan_channel_is_busy(uint32_t channel_id) { - // TODO: assert channel_id is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); return *status_ptr & (1 << channel_id); } static void mchan_channel_wait(uint32_t channel_id) { - // TODO: assert channel_id is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); #if defined(MCHAN_EVENT) while (mchan_channel_is_busy(channel_id)) eu_evt_maskWaitAndClr(1 << MCHAN_EVENT_BIT); diff --git a/TargetLibraries/PULPOpen/inc/mchan_v7.h b/TargetLibraries/PULPOpen/inc/mchan_v7.h index 1078584b5a..32ef836f34 100644 --- a/TargetLibraries/PULPOpen/inc/mchan_v7.h +++ b/TargetLibraries/PULPOpen/inc/mchan_v7.h @@ -7,6 +7,8 @@ #ifndef __MCHAN_V7_H__ #define __MCHAN_V7_H__ +#include "assert.h" + // Requires to have MCHAN_BASE_ADDR, MCHAN_EVENT defined outside of header #ifndef MCHAN_BASE_ADDR #error "[mchan_v7.h] MCHAN_BASE_ADDR not defined!" @@ -34,6 +36,7 @@ #include "pmsis.h" #define MCHAN_TRANSFER_LEN_SIZE (17) +#define MCHAN_CHANNEL_ID_MAX (15) #define MCHAN_CMD_FLAG_DIRECTION_LOC2EXT (0 << (MCHAN_TRANSFER_LEN_SIZE + 0)) #define MCHAN_CMD_FLAG_DIRECTION_EXT2LOC (1 << (MCHAN_TRANSFER_LEN_SIZE + 0)) @@ -94,17 +97,17 @@ static void mchan_transfer_2d_loc_strided_ext_strided( static uint32_t mchan_channel_alloc() { return *cmd_ptr; } static void mchan_channel_free(uint32_t channel_id) { - // TODO: assert tid is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); *status_ptr = 1 << channel_id; } static uint32_t mchan_channel_is_busy(uint32_t channel_id) { - // TODO: assert tid is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); return *status_ptr & (1 << channel_id); } static void mchan_channel_wait(uint32_t channel_id) { - // TODO: assert tid is smaller then 32 + assert(channel_id <= MCHAN_CHANNEL_ID_MAX); #if defined(MCHAN_EVENT) while (mchan_channel_is_busy(channel_id)) eu_evt_maskWaitAndClr(1 << MCHAN_EVENT_BIT); diff --git a/TargetLibraries/Snitch/src/CycleCounter.c b/TargetLibraries/Snitch/src/CycleCounter.c index 47724816f1..3861c421c1 100644 --- a/TargetLibraries/Snitch/src/CycleCounter.c +++ b/TargetLibraries/Snitch/src/CycleCounter.c @@ -14,7 +14,7 @@ static uint32_t instr_end[NUM_CORES] __attribute__((section(".l1"))); static uint32_t running[NUM_CORES] __attribute__((section(".l1"))); void ResetTimer() { - // snrt_reset_perf_counter(SNRT_PERF_CNT0); + snrt_reset_perf_counter(SNRT_PERF_CNT0); uint32_t const core_id = snrt_global_core_idx(); uint32_t _timer_init = read_csr(mcycle); uint32_t _instr_init = read_csr(minstret); @@ -26,7 +26,9 @@ void ResetTimer() { } void StartTimer() { - // snrt_start_perf_counter(SNRT_PERF_CNT0, SNRT_PERF_CNT_CYCLES, 0); + if (snrt_is_dm_core()) { + snrt_start_perf_counter(SNRT_PERF_CNT0, SNRT_PERF_CNT_CYCLES, 0); + } uint32_t const core_id = snrt_global_core_idx(); timer_init[core_id] = read_csr(mcycle); instr_init[core_id] = read_csr(minstret); @@ -34,17 +36,16 @@ void StartTimer() { } void StopTimer() { - // if (!snrt_is_dm_core()) { - // snrt_stop_perf_counter(SNRT_PERF_CNT0); - // } + if (snrt_is_dm_core()) { + snrt_stop_perf_counter(SNRT_PERF_CNT0); + } uint32_t const core_id = snrt_global_core_idx(); timer_end[core_id] = read_csr(mcycle); - timer_end[core_id] = read_csr(minstret); + instr_end[core_id] = read_csr(minstret); running[core_id] = 0; } uint32_t getCycles() { - // return snrt_get_perf_counter(SNRT_PERF_CNT0); uint32_t const core_id = snrt_global_core_idx(); if (running[core_id]) { return read_csr(mcycle) - timer_init[core_id]; From 479593289e87bd6cd98910d000103264ac3d4fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C4=83lin=20Diaconu?= Date: Tue, 11 Nov 2025 17:18:26 +0100 Subject: [PATCH 19/28] TinyViT on non-tiled Siracusa (#117) This PR brings the changes required for a working minimal TinyViT on the Siracusa platform, without tiling. ## Added - PULP 2D FP DW conv Im2Col template and kernel, with bias support. - Bias support for PULP 2D FP regular conv Im2Col in template & kernel. - PULP FP DW conv 2D parser. - FP conv 2D (simple & DW), reshape & skip connection, and TinyViT demo tests to the non-tiled Siracusa CI pipeline. - FP bindings and mappings for PULP slice, DW conv 2D, and reduce mean operations. - FP PULP DW conv lowering optimization pass similar to the existent one for integer version. - RemoveEmptyConvBiasPass to the PULP optimizer. - PULPClusterEngine now accepts a `n_cores` parameter to set the number of cores used - annotateNCores method to PULPDeployer that adds an `n_cores` key to all PULPClusterEngine templates' operatorRepresentations ## Changed - Reduced size of reshape & skip connection test, for non-tiled Siracusa memory compatibility. - changed _mapNode to _selectEngine which reduces the responsibility of that function to, as the name states, just engine selection ## Fixed - Fixed bug for non-batched elements in the PULPOpen FP GEMM and matmul templates. - Added underscore to the beginning of closure names to avoid naming issues when they start with unsupported first characters (like numbers). - Data types in the PULPOpen FP add and mul templates. --- .github/workflows/ci-platform-siracusa.yml | 10 + CHANGELOG.md | 23 +- .../CodeTransformationPasses/Closure.py | 3 +- Deeploy/CommonExtensions/DataTypes.py | 10 +- .../NetworkDeployerWrapper.py | 8 +- Deeploy/DeeployTypes.py | 11 +- .../EngineColoringDeployer.py | 8 +- Deeploy/Targets/PULPOpen/Bindings.py | 51 ++-- Deeploy/Targets/PULPOpen/Deployer.py | 24 +- Deeploy/Targets/PULPOpen/Parsers.py | 91 ++++++- Deeploy/Targets/PULPOpen/Platform.py | 27 +- .../{SliceTemplate.py => DMASliceTemplate.py} | 0 .../PULPOpen/Templates/FloatAddTemplate.py | 12 +- .../PULPOpen/Templates/FloatConvTemplate.py | 81 +++++- .../PULPOpen/Templates/FloatGemmTemplate.py | 9 + .../PULPOpen/Templates/FloatMatMulTemplate.py | 10 + .../PULPOpen/Templates/FloatMulTemplate.py | 8 +- .../PULPOpen/Templates/ReshapeTemplate.py | 26 +- .../inputs.npz | Bin 3706004 -> 2996 bytes .../network.onnx | Bin 3693436 -> 2569 bytes .../outputs.npz | Bin 4104 -> 328 bytes DeeployTest/generateNetwork.py | 13 +- DeeployTest/testMVP.py | 12 + DeeployTest/testUtils/testRunner.py | 4 + TargetLibraries/PULPOpen/inc/kernel/Conv.h | 32 ++- .../PULPOpen/src/Convolution_fp32.c | 196 ++++++++++---- .../PULPOpen/src/DWConvolution_fp32.c | 251 ++++++++++++++++++ 27 files changed, 766 insertions(+), 154 deletions(-) rename Deeploy/Targets/PULPOpen/Templates/{SliceTemplate.py => DMASliceTemplate.py} (100%) create mode 100644 TargetLibraries/PULPOpen/src/DWConvolution_fp32.c diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml index 7c6a5f7541..f59f7fa884 100644 --- a/.github/workflows/ci-platform-siracusa.yml +++ b/.github/workflows/ci-platform-siracusa.yml @@ -53,7 +53,15 @@ jobs: testBacktracking testFloatAdder testFloatGEMM + testFloat2DConvolution + testFloat2DConvolutionBias + testFloat2DConvolutionZeroBias + + testFloat2DDWConvolution + testFloat2DDWConvolutionBias + testFloat2DDWConvolutionZeroBias + testFloatLayerNorm testFloatRelu testFloatMaxPool @@ -64,6 +72,7 @@ jobs: Quant Dequant testFloatReduceSum + testFloatReshapeWithSkipConnection testFloatSoftmaxGrad testFloatSoftmaxCrossEntropy testFloatSoftmaxCrossEntropyGrad @@ -87,4 +96,5 @@ jobs: CCT/CCT_1_16_16_8 CCT/CCT_2_32_32_128_Opset20 testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8 + testFloatDemoTinyViT num-cores: 8 diff --git a/CHANGELOG.md b/CHANGELOG.md index faf4de42c5..1ed34f8da9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid ## Unreleased (Planned Release Target: v0.2.1) ### List of Pull Requests +- TinyViT on non-tiled Siracusa [#117](https://github.com/pulp-platform/Deeploy/pull/117) - Support Fully Asynchronous DMAs [#114](https://github.com/pulp-platform/Deeploy/pull/114) - Disallow shape inference [#128](https://github.com/pulp-platform/Deeploy/pull/128) - Remove memory-aware node bindings [#123](https://github.com/pulp-platform/Deeploy/pull/123) @@ -24,6 +25,13 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Fix bias hoisting in generic GEMM with no bias [#126](https://github.com/pulp-platform/Deeploy/pull/126) ### Added +- PULP 2D FP DW conv Im2Col template and kernel, with bias support. +- Bias support for PULP 2D FP regular conv Im2Col in template & kernel. +- PULP FP DW conv 2D parser. +- FP conv 2D (simple & DW), reshape & skip connection, and TinyViT demo tests to the non-tiled Siracusa CI pipeline. +- FP bindings and mappings for PULP slice, DW conv 2D, and reduce mean operations. +- FP PULP DW conv lowering optimization pass similar to the existent one for integer version. +- RemoveEmptyConvBiasPass to the PULP optimizer. - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough - Added a `testTypeInferenceDifferentTypes` test case to validate type inference for different input types - Added `_mangleNodeNames` function to avoid duplicate node mappings @@ -58,8 +66,11 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Added testFloatGEMMnobias - Profiling support and optional comments in generated DMA code for better traceability - Added new waiting-strategy logic with fine-grained `PerTensorWaitingStrategy` +- PULPClusterEngine now accepts a `n_cores` parameter to set the number of cores used +- annotateNCores method to PULPDeployer that adds an `n_cores` key to all PULPClusterEngine templates' operatorRepresentations ### Changed +- Reduced size of reshape & skip connection test, for non-tiled Siracusa memory compatibility. - Replaced platform-specific tags (`*-amd64`, `*-arm64`) with direct digest references in `Noelware/docker-manifest-action`. - mchan HAL is now reduced to bare-bones - refactor of the IntrospectiveCodeTransformation to work on the Mako template @@ -95,8 +106,12 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Disabled ICCT_ITA_8 MemPool test because it was using a lowering that created shapeless tensors - Added missing shape annotation to the testTypeInferenceDifferentTypes - Refactored DMA code generation (`SnitchDma`, `Mchan`) to correctly overlap transfers and compute in double-buffering mode +- changed `_mapNode` to `_selectEngine` which reduces the responsibility of that function to, as the name states, just engine selection ### Fixed +- Fixed bug for non-batched elements in the PULPOpen FP GEMM and matmul templates. +- Added underscore to the beginning of closure names to avoid naming issues when they start with unsupported first characters (like numbers). +- Data types in the PULPOpen FP add and mul templates. - Prevent node duplication for graphs generated via GraphSurgeon - Resolved issue with missing `id` in the `Build Cache for Docker` step, used in the `Inject build-cache` step. - Fix license CI check and prevent potential issues with `jq` installation @@ -185,9 +200,9 @@ This release containing major architectural changes, new platform support, enhan ### Added -- BatchNorm kernel -- ConvTranspose kernel -- MaxPool1D kernel +- BatchNorm kernel +- ConvTranspose kernel +- MaxPool1D kernel - Template for 1D Convolution - Support for float32 data type in the previous kernels - Float binding for Pad1D kernel @@ -326,7 +341,7 @@ This release containing major architectural changes, new platform support, enhan ### Changed - FloatConvTemplate file -- Platform.py file +- Platform.py file - Bump the CMake version to 3.24 as required for the chimera-sdk - Bump GVSoC's version and add chimera simulation target - Rename the generic source util to utils to avoid name collision with chimera-sdk diff --git a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py index c5f9c883af..41073ad646 100644 --- a/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py +++ b/Deeploy/CommonExtensions/CodeTransformationPasses/Closure.py @@ -155,7 +155,8 @@ def apply(self, executionBlock: ExecutionBlock, name: str, verbose: CodeGenVerbosity = _NoVerbosity) -> Tuple[NetworkContext, ExecutionBlock]: - self.closureName = name + self.closureSuffix + # Prepend underscore to avoid name issues when beginning with problematic characters (like numbers) + self.closureName = "_" + name + self.closureSuffix self.functionCall = executionBlock.generate(ctxt) self._generateClosureStruct(ctxt, executionBlock) ctxt = self._generateClosureCtxt(ctxt, name) diff --git a/Deeploy/CommonExtensions/DataTypes.py b/Deeploy/CommonExtensions/DataTypes.py index 4f6dba3827..c05ea3b9d9 100644 --- a/Deeploy/CommonExtensions/DataTypes.py +++ b/Deeploy/CommonExtensions/DataTypes.py @@ -87,11 +87,11 @@ class float64_t(FloatImmediate): SignedIntegerDataTypes: Tuple[Type[IntegerImmediate], ...] = (int8_t, int16_t, int32_t, int64_t) UnsignedIntegerDataTypes: Tuple[Type[IntegerImmediate], ...] = (uint8_t, uint16_t, uint32_t, uint64_t) -IntegerDataTypes: Tuple[Type[IntegerImmediate], ...] = (sorted(( - *SignedIntegerDataTypes, - *UnsignedIntegerDataTypes, -), - key = lambda _type: _type.typeWidth)) +IntegerDataTypes: Tuple[Type[IntegerImmediate], ...] = tuple( + sorted(( + *SignedIntegerDataTypes, + *UnsignedIntegerDataTypes, + ), key = lambda _type: _type.typeWidth)) FloatDataTypes: Tuple[Type[FloatImmediate], ...] = (bfloat16_t, float16_t, float32_t, float64_t) diff --git a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py index f07fe57c96..a8f27b5463 100644 --- a/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py +++ b/Deeploy/CommonExtensions/NetworkDeployers/NetworkDeployerWrapper.py @@ -2,11 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Union - import onnx_graphsurgeon as gs -from Deeploy.DeeployTypes import CodeGenVerbosity, NetworkContext, NetworkDeployer, ONNXLayer, _NoVerbosity +from Deeploy.DeeployTypes import CodeGenVerbosity, DeploymentEngine, NetworkContext, NetworkDeployer, _NoVerbosity class NetworkDeployerWrapper(NetworkDeployer): @@ -68,8 +66,8 @@ def generateBufferAllocationCode(self) -> str: return self._innerObject.generateBufferAllocationCode() # MultiEngineDeployer augment - def _mapNode(self, node: gs.Node) -> Union[ONNXLayer, Any]: - return self._innerObject._mapNode(node) + def _selectEngine(self, node: gs.Node) -> DeploymentEngine: + return self._innerObject._selectEngine(node) def _printMemorySummary(self): return self._innerObject._printMemorySummary() diff --git a/Deeploy/DeeployTypes.py b/Deeploy/DeeployTypes.py index 8c2f5d2485..5ccfb7dcf7 100644 --- a/Deeploy/DeeployTypes.py +++ b/Deeploy/DeeployTypes.py @@ -325,7 +325,7 @@ def fromNode(cls, node: gs.Node): return (cls(name = node.name, shape = node.shape if not isinstance(node, gs.Constant) else node.values.shape)) def has_live_aliases(self, ctxt: NetworkContext) -> bool: - """Checks whether this VariableBuffer has any live ancestors, i.e. buffers that are still live and are aliased by this buffer. + """Checks whether this VariableBuffer has any live aliases, i.e. buffers that are still live and are aliased by this buffer. Parameters ---------- ctxt : NetworkContext @@ -333,7 +333,7 @@ def has_live_aliases(self, ctxt: NetworkContext) -> bool: Returns ------- bool - True if this VariableBuffer has any live ancestors, False otherwise + True if this VariableBuffer has any live aliases, False otherwise """ # Do a breadth-first search across the aliasing double-linked list live = self._live @@ -2562,10 +2562,10 @@ def codeTransform(self, verbose: CodeGenVerbosity = _NoVerbosity): self.ctxt = layer.codeTransform(self.ctxt, verbose) self.transformed = True - def _mapNode(self, node: gs.Node) -> Union[ONNXLayer, Any]: + def _selectEngine(self, node: gs.Node) -> DeploymentEngine: for engine in self.Platform.engines: if node.op in engine.Mapping: - return engine.Mapping[node.op](node) + return engine raise RuntimeError(f"No mapping found for node {node.name} with op type {node.op}") def _bindLayers(self): @@ -2582,7 +2582,8 @@ def _bindLayers(self): flatSchedule += subGraph for node in flatSchedule: - layer = self._mapNode(node) + engine = self._selectEngine(node) + layer = engine.Mapping[node.op](node) if isinstance(layer, ONNXLayer): log.debug(f" {SUCCESS_MARK} Bind {node.name} to layer {layer.__class__.__name__}") self.layerBinding[layer.node.name] = layer diff --git a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py index 4b05ab5be4..570363b9a2 100644 --- a/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py +++ b/Deeploy/EngineExtension/NetworkDeployers/EngineColoringDeployer.py @@ -2,13 +2,13 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Callable, Dict, Type, Union +from typing import Callable, Dict, Type import onnx_graphsurgeon as gs from Deeploy.AbstractDataTypes import Pointer from Deeploy.CommonExtensions.NetworkDeployers.NetworkDeployerWrapper import NetworkDeployerWrapper -from Deeploy.DeeployTypes import DeploymentPlatform, NetworkDeployer, ONNXLayer, Schedule, TopologyOptimizer +from Deeploy.DeeployTypes import DeploymentEngine, DeploymentPlatform, NetworkDeployer, Schedule, TopologyOptimizer from Deeploy.EngineExtension.OptimizationPasses.TopologyOptimizationPasses.EngineColoringPasses import \ EngineColoringPass, EngineMapper @@ -48,14 +48,14 @@ def lower(self, graph: gs.Graph) -> gs.Graph: ) == 0, f"Missing engine color for nodes {[node.name for node in uncoloredNodes]} with operations {uncoloredOperations}" return graph - def _mapNode(self, node: gs.Node) -> Union[ONNXLayer, Any]: + def _selectEngine(self, node: gs.Node) -> DeploymentEngine: assert "engine" in node.attrs, f"Node {node.name} doesn't have an engine color." engineName = node.attrs["engine"] assert isinstance(engineName, str) and engineName in self.engineDict, \ f"Node {node.name} has an invalid engine {engineName} assigned." engine = self.engineDict[engineName] assert node.op in engine.Mapping, f"No mapping found for {node.op} in engine {engine.name}" - return engine.Mapping[node.op](node) + return engine class EngineColoringDeployerWrapper(EngineColoringDeployer, NetworkDeployerWrapper): diff --git a/Deeploy/Targets/PULPOpen/Bindings.py b/Deeploy/Targets/PULPOpen/Bindings.py index 9ff940b2f0..cc81527f32 100644 --- a/Deeploy/Targets/PULPOpen/Bindings.py +++ b/Deeploy/Targets/PULPOpen/Bindings.py @@ -9,13 +9,13 @@ from Deeploy.CommonExtensions.CodeTransformationPasses.Closure import ClosureGeneration, MemoryAwareClosureGeneration from Deeploy.CommonExtensions.CodeTransformationPasses.MemoryAllocation import ArgumentStructGeneration, \ MemoryManagementGeneration, MemoryPassthroughGeneration -from Deeploy.CommonExtensions.DataTypes import IntegerDataTypes, SignedIntegerDataTypes, float32_t, int8_t, int32_t, \ - uint8_t +from Deeploy.CommonExtensions.DataTypes import FloatDataTypes, IntegerDataTypes, SignedIntegerDataTypes, float32_t, \ + int8_t, int32_t, int64_t, uint8_t from Deeploy.DeeployTypes import CodeTransformation, NodeBinding, NodeTemplate from Deeploy.FutureExtension.Bindings.AutoFutureBinding import AutoFutureBinding from Deeploy.FutureExtension.CodeTransformationPasses.FutureCodeTransformation import FutureGeneration -from Deeploy.Targets.Generic.Templates import AddTemplate, ConcatTemplate, DequantTemplate, FloatReduceSumTemplate, \ - GatherTemplate, QuantTemplate, RQSiGELUTemplate, iHardswishTemplate +from Deeploy.Targets.Generic.Templates import AddTemplate, ConcatTemplate, DequantTemplate, FloatReduceMeanTemplate, \ + FloatReduceSumTemplate, GatherTemplate, QuantTemplate, RQSiGELUTemplate, SliceTemplate, iHardswishTemplate from Deeploy.Targets.Generic.TypeCheckers import AddChecker, ConcatChecker, ConvChecker, DequantChecker, \ GatherChecker, GELUChecker, GEMMChecker, HardswishChecker, LayerNormChecker, MatMulChecker, MulChecker, \ QuantChecker, ReduceMeanChecker, ReluChecker, ReshapeChecker, RQAddChecker, RQHardswishChecker, SGDChecker, \ @@ -27,11 +27,11 @@ from Deeploy.Targets.PULPOpen.DataTypes import PULPDMAFuture from Deeploy.Targets.PULPOpen.DMA.L3Dma import l3DmaHack from Deeploy.Targets.PULPOpen.DMA.MchanDma import MchanDma -from Deeploy.Targets.PULPOpen.Templates import ConvTemplate, FloatAddTemplate, FloatConvTemplate, FloatGELUTemplate, \ - FloatGemmTemplate, FloatLayernormTemplate, FloatMatMulTemplate, FloatMaxPoolTemplate, FloatMulTemplate, \ - FloatReluTemplate, FloatSoftmaxTemplate, GEMMTemplate, MatrixVectorTemplate, MaxPool2DTemplate, MulTemplate, \ - ReduceMeanTemplate, RequantShiftTemplate, ReshapeTemplate, RQAddTemplate, RQSiHardswishTemplate, SGDTemplate, \ - SliceTemplate, SoftmaxCrossEntropyLossTemplate, TallGEMMTemplate, TransposeTemplate, UniformRequantShiftTemplate, \ +from Deeploy.Targets.PULPOpen.Templates import ConvTemplate, DMASliceTemplate, FloatAddTemplate, FloatConvTemplate, \ + FloatGELUTemplate, FloatGemmTemplate, FloatLayernormTemplate, FloatMatMulTemplate, FloatMaxPoolTemplate, \ + FloatMulTemplate, FloatReluTemplate, FloatSoftmaxTemplate, GEMMTemplate, MatrixVectorTemplate, MaxPool2DTemplate, \ + MulTemplate, ReduceMeanTemplate, RequantShiftTemplate, ReshapeTemplate, RQAddTemplate, RQSiHardswishTemplate, \ + SGDTemplate, SoftmaxCrossEntropyLossTemplate, TallGEMMTemplate, TransposeTemplate, UniformRequantShiftTemplate, \ iRMSNormTemplate, iSoftmaxTemplate from Deeploy.Targets.PULPOpen.TypeCheckers import PULPConvChecker, PULPLinearChecker, PULPMaxPoolChecker, \ PULPRequantShiftChecker @@ -148,16 +148,24 @@ PointerClass(uint8_t), PointerClass(uint8_t), PointerClass(uint8_t) - ], [PULPDMAFuture(underlyingType = type)]), SliceTemplate.referenceTemplate, MemoryAwareForkTransformer) + ], [PULPDMAFuture(underlyingType = type)]), DMASliceTemplate.referenceTemplate, MemoryAwareForkTransformer) for type in IntegerDataTypes ] +PULPSliceBindings = [ + NodeBinding( + SliceChecker([ + PointerClass(type), + PointerClass(uint8_t), + PointerClass(uint8_t), + PointerClass(uint8_t), + PointerClass(uint8_t) + ], [PointerClass(type)]), SliceTemplate.referenceTemplate, ForkTransformer) for type in FloatDataTypes +] + PULPReshapeBindings = [ - NodeBinding(ReshapeChecker([PointerClass(type), PointerClass(int32_t)], [PointerClass(type)]), - ReshapeTemplate.referenceTemplate, SkipTransformer) for type in IntegerDataTypes -] + [ - NodeBinding(ReshapeChecker([PointerClass(float32_t), PointerClass(type)], [PointerClass(float32_t)]), - ReshapeTemplate.referenceTemplate, SkipTransformer) for type in IntegerDataTypes + NodeBinding(ReshapeChecker([PointerClass(type), PointerClass(int64_t)], [PointerClass(type)]), + ReshapeTemplate.referenceTemplate, SkipTransformer) for type in IntegerDataTypes + FloatDataTypes ] PULPRQAddBindings = [ @@ -225,6 +233,14 @@ ForkTransformer) ] +PULPFloatDWConv2DBindings = [ + NodeBinding( + ConvChecker( + [PointerClass(float_type), PointerClass(float_type), + PointerClass(float_type)], [PointerClass(float_type)]), FloatConvTemplate.referenceDW2DIm2ColTemplate, + ForkTransformer) for float_type in FloatDataTypes +] + PULPRQSMatrixVecBindings = [ NodeBinding( PULPLinearChecker([PointerClass(type1), @@ -276,6 +292,11 @@ PULPReduceMeanBindings = [ NodeBinding(ReduceMeanChecker([PointerClass(type)], [PointerClass(type)]), ReduceMeanTemplate.referenceTemplate, ClusterTransformer) for type in IntegerDataTypes +] + [ + NodeBinding(ReduceMeanChecker([PointerClass(float_type), PointerClass(integer_type)], [PointerClass(float_type)]), + FloatReduceMeanTemplate.referenceTemplate, ClusterTransformer) + for integer_type in SignedIntegerDataTypes + for float_type in FloatDataTypes ] PULPReduceSumBindings = [ diff --git a/Deeploy/Targets/PULPOpen/Deployer.py b/Deeploy/Targets/PULPOpen/Deployer.py index 86bf02e578..bceea01f4d 100644 --- a/Deeploy/Targets/PULPOpen/Deployer.py +++ b/Deeploy/Targets/PULPOpen/Deployer.py @@ -15,6 +15,7 @@ from Deeploy.DeeployTypes import ConstantBuffer, DeploymentPlatform, NodeTemplate, TopologyOptimizer, VariableBuffer from Deeploy.Targets.Generic.TopologyOptimizationPasses.Passes import ReshapeConstOptPass, TransposeConstOptPass, \ TransposeMergePass, TransposeNoPermOptPass, TransposeSplitPass +from Deeploy.Targets.PULPOpen.Platform import PULPClusterEngine from Deeploy.Targets.PULPOpen.TopologyOptimizationPasses.Passes import RQAddTransposeSquashPass _L3AllocTemplate = NodeTemplate(""" @@ -63,7 +64,15 @@ def __init__(self, self.extNameCount = 0 - def bind(self): + def annotateNCores(self) -> None: + for layer in self.layerBinding.values(): + node = layer.node + engine = self._selectEngine(node) + opRepr = layer.mapper.parser.operatorRepresentation + if isinstance(engine, PULPClusterEngine): + opRepr["n_cores"] = engine.n_cores + + def bind(self) -> bool: # SCHEREMO: THIS IS A STOP GAP SOLUTION. DONT REUSE. I MEAN IT. I WILL FIND YOU. # SCHEREMO: The BindingOptimizationPass system is fairly fragile; # it was designed this way because implementing further topology optimizations after @@ -71,11 +80,16 @@ def bind(self): # but if there is only very few cases, this solution is okay. autoTransposePass = AutoTransposeMergePass() #self.ctxt, self.layerBinding = autoTransposePass.apply(self.ctxt, self.graph, self.layerBinding) + + # LMACAN: THIS IS A STOP GAP SOLUTION. DONT REUSE. I MEAN IT. I WILL FIND YOU. + self.annotateNCores() + # SCHEREMO: THIS IS A STOP GAP SOLUTION. DONT REUSE. I MEAN IT. I WILL FIND YOU. - ret = super().bind() - if ret: - self.ctxt.hoistGlobalDefinition("cluster_dev", "extern struct pi_device cluster_dev;") - return ret + if not super().bind(): + return False + + self.ctxt.hoistGlobalDefinition("cluster_dev", "extern struct pi_device cluster_dev;") + return True def _l3ConstBuffer(self) -> List[VariableBuffer]: return [ diff --git a/Deeploy/Targets/PULPOpen/Parsers.py b/Deeploy/Targets/PULPOpen/Parsers.py index e94af6e420..ab99fcabc6 100644 --- a/Deeploy/Targets/PULPOpen/Parsers.py +++ b/Deeploy/Targets/PULPOpen/Parsers.py @@ -72,24 +72,24 @@ def parseNode(self, node: gs.Node) -> (bool): wellFormed = super().parseNode(node) if wellFormed: ret = all([ - # Make sure padding is square + # Current PULP kernel only supports grouping of 1 self.operatorRepresentation['group'] == 1, + + # Make sure padding is square self.operatorRepresentation['pads'][0] == self.operatorRepresentation['pads'][2], self.operatorRepresentation['pads'][1] == self.operatorRepresentation['pads'][3], self.operatorRepresentation['pads'][0] == self.operatorRepresentation['pads'][1], - len(node.inputs) == 2 + + # Check number of inputs + # 2 inputs if no bias, 3 if layer has bias + len(node.inputs) in [2, 3], ]) - self.operatorRepresentation['dim_kernel_x'] = int(self.operatorRepresentation['kernel_shape'][0]) - self.operatorRepresentation['dim_kernel_y'] = int(self.operatorRepresentation['kernel_shape'][1]) - self.operatorRepresentation['dilation_x'] = int(self.operatorRepresentation['dilations'][0]) - self.operatorRepresentation['dilation_y'] = int(self.operatorRepresentation['dilations'][1]) + # Extract additional attributes self.operatorRepresentation['padding_y_top'] = int(self.operatorRepresentation['pads'][0]) self.operatorRepresentation['padding_x_left'] = int(self.operatorRepresentation['pads'][1]) self.operatorRepresentation['padding_y_bottom'] = int(self.operatorRepresentation['pads'][2]) self.operatorRepresentation['padding_x_right'] = int(self.operatorRepresentation['pads'][3]) - self.operatorRepresentation['stride_x'] = int(self.operatorRepresentation['strides'][0]) - self.operatorRepresentation['stride_y'] = int(self.operatorRepresentation['strides'][1]) return ret return False @@ -102,11 +102,86 @@ def parseNodeCtxt(self, newCtxt, ret = super().parseNodeCtxt(ctxt, node, channels_first) if ret: + # Set inputs names + inputs = ['data_in', 'weight'] + + # Handle bias, if present + if len(node.inputs) == 2: + self.operatorRepresentation["has_bias"] = "false" + self.operatorRepresentation["bias"] = "NULL" + else: + inputs.append("bias") + self.operatorRepresentation["has_bias"] = "true" + + for idx, inputNode in enumerate(node.inputs): + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name + return newCtxt, True return ctxt, False +class PULPFPDWConv2DParser(Conv2DParser): + + def __init__(self, noBiasHoisting = True): + super().__init__(noBiasHoisting) + + def parseNode(self, node: gs.Node) -> (bool): + # Parse root conv 2D information + wellFormed = super().parseNode(node) + + if wellFormed: + # Check if the node is a depthwise convolution + ret = all([ + # Make sure padding is square + self.operatorRepresentation['pads'][0] == self.operatorRepresentation['pads'][2], + self.operatorRepresentation['pads'][1] == self.operatorRepresentation['pads'][3], + self.operatorRepresentation['pads'][0] == self.operatorRepresentation['pads'][1], + + # Check number of inputs + # 2 inputs if no bias, 3 if layer has bias + len(node.inputs) in [2, 3], + ]) + + # Extract additional attributes + self.operatorRepresentation['padding_y_top'] = int(self.operatorRepresentation['pads'][0]) + self.operatorRepresentation['padding_x_left'] = int(self.operatorRepresentation['pads'][1]) + self.operatorRepresentation['padding_y_bottom'] = int(self.operatorRepresentation['pads'][2]) + self.operatorRepresentation['padding_x_right'] = int(self.operatorRepresentation['pads'][3]) + + return ret + return False + + def parseNodeCtxt(self, + ctxt: NetworkContext, + node: gs.Node, + channels_first: bool = True) -> Tuple[NetworkContext, bool]: + # Parse node context for 2D conv + newCtxt, ret = super().parseNodeCtxt(ctxt, node, channels_first) + + if ret: + # Define input names + inputs = ['data_in', 'weight'] + + # Handle bias, if present + if len(node.inputs) == 2: + self.operatorRepresentation["has_bias"] = "false" + self.operatorRepresentation["bias"] = "NULL" + else: + inputs.append("bias") + self.operatorRepresentation["has_bias"] = "true" + + # Map input nodes to operator representation + for idx, inputNode in enumerate(node.inputs): + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name + + # Check if DW + if self.operatorRepresentation['group'] == self.operatorRepresentation['ch_im_in']: + return newCtxt, True + + return ctxt, False + + class PULPDWConv1DParser(RQSConv1DParser): def __init__(self, noBiasHoisting = True): diff --git a/Deeploy/Targets/PULPOpen/Platform.py b/Deeploy/Targets/PULPOpen/Platform.py index 99c1c93351..fc2ae8a1fa 100644 --- a/Deeploy/Targets/PULPOpen/Platform.py +++ b/Deeploy/Targets/PULPOpen/Platform.py @@ -5,6 +5,8 @@ import numpy as np import onnx_graphsurgeon as gs +from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ + RemoveEmptyConvBiasPass from Deeploy.DeeployTypes import ConstantBuffer, DeploymentEngine, DeploymentPlatform, NetworkContext, NodeMapper, \ NodeTemplate, StructBuffer, TopologyOptimizer, TransientBuffer, VariableBuffer from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel @@ -27,10 +29,11 @@ MergeConstAddAndRequantPass, MergeTrueIntegerDivRequantShiftPass, QuantPatternPass, RQSSplitPass, \ SkipEmptyConcatPass, SkipUnityRequantPass, iGELURequantMergePass, iHardswishRequantMergePass from Deeploy.Targets.PULPOpen.Bindings import BasicDequantBindings, BasicQuantBindings, PULPConv1DBinding, \ - PULPDMASliceBindings, PULPDWConv1DBinding, PULPReduceMeanBindings + PULPDMASliceBindings, PULPDWConv1DBinding, PULPFloatDWConv2DBindings, PULPReduceMeanBindings, PULPSliceBindings from Deeploy.Targets.PULPOpen.Layers import PULPRQSConvLayer, PULPRQSGEMMLayer from Deeploy.Targets.PULPOpen.Parsers import PULPConv1DParser, PULPConv2DParser, PULPDWConv1DParser, \ - PULPDWConv2DParser, PULPFPConv2DParser, PULPGEMMParser, PULPMatrixVecParser, PULPTallGEMMParser + PULPDWConv2DParser, PULPFPConv2DParser, PULPFPDWConv2DParser, PULPGEMMParser, PULPMatrixVecParser, \ + PULPTallGEMMParser from Deeploy.Targets.PULPOpen.Templates import AllocateTemplate, FreeTemplate from Deeploy.Targets.PULPOpen.Tiler import PULPAddTilingReadyBindings, PULPConcatTilingReadyBindings, \ PULPConv2DTilingReadyBindings, PULPFlattenTilingReadyBindings, PULPFPGELUTilingReadyBindings, \ @@ -71,6 +74,7 @@ DWConv1DMapper = NodeMapper(PULPDWConv1DParser(), [PULPDWConv1DBinding]) FPConv2DMapper = NodeMapper(PULPFPConv2DParser(), PULPConv2DTilingReadyBindings) Conv2DMapper = NodeMapper(PULPConv2DParser(), PULPRQSConv2DTilingReadyBindings) +FPDWConv2DMapper = NodeMapper(PULPFPDWConv2DParser(), PULPFloatDWConv2DBindings) DWConv2DMapper = NodeMapper(PULPDWConv2DParser(), PULPRQSDWConv2DTilingReadyBindings) GEMMMapper = NodeMapper(PULPGEMMParser(), PULPRQSGEMMTilingReadyBindings) FloatGEMMMapper = NodeMapper(GEMMParser(), PULPFPGEMMTilingReadyBindings) @@ -85,7 +89,9 @@ ConcatMapper = NodeMapper(ConcatParser(), PULPConcatTilingReadyBindings) -SliceMapper = NodeMapper(SliceParser(), PULPDMASliceBindings) +DMASliceMapper = NodeMapper(SliceParser(), PULPDMASliceBindings) + +SliceMapper = NodeMapper(SliceParser(), PULPSliceBindings) iRMSNormMapper = NodeMapper(iRMSNormParser(), PULPiRMSNormTilingReadyBindings) @@ -99,7 +105,7 @@ DequantMapper = NodeMapper(DequantParser(), BasicDequantBindings) GEMMDequantMapper = NodeMapper(PULPGEMMParser(), BasicGEMMBindings) PULPMapping = { - 'Conv': ConvLayer([FPConv2DMapper]), + 'Conv': ConvLayer([FPConv2DMapper, FPDWConv2DMapper]), 'RequantizedConv': PULPRQSConvLayer([Conv2DMapper, DWConv2DMapper, Conv1DMapper, DWConv1DMapper]), 'RequantizedGemm': PULPRQSGEMMLayer([MatrixVecMapper, TallGEMMMapper, GEMMMapper]), 'Gemm': GEMMLayer([FloatGEMMMapper, GEMMDequantMapper]), @@ -125,7 +131,7 @@ 'Squeeze': ReshapeLayer([UnsqueezeMapper]), 'Transpose': TransposeLayer([TransposeMapper]), 'Unsqueeze': ReshapeLayer([UnsqueezeMapper]), - 'Slice': SliceLayer([SliceMapper]), + 'Slice': SliceLayer([SliceMapper, DMASliceMapper]), 'RequantizedAdd': AddLayer([RQAddMapper]), 'Concat': ConcatLayer([ConcatMapper]), 'iRMSNorm': iRMSNormLayer([iRMSNormMapper]), @@ -225,7 +231,8 @@ class PULPStructBuffer(StructBuffer): MergeConstAddAndRequantPass(), PULPGEMMRequantMergePass(), PULPMatMulRequantMergePass(), - PULPAddRequantMergePass() + PULPAddRequantMergePass(), + RemoveEmptyConvBiasPass(), ], name = "PULPOptimizer") @@ -237,8 +244,14 @@ class PULPStructBuffer(StructBuffer): class PULPClusterEngine(DeploymentEngine): - def __init__(self, name: str, Mapping = PULPMapping, initCode = "", includeList = _includeList) -> None: + def __init__(self, + name: str, + Mapping = PULPMapping, + initCode = "", + includeList = _includeList, + n_cores: int = 8) -> None: super().__init__(name, Mapping, initCode, includeList) + self.n_cores = n_cores class PULPPlatform(DeploymentPlatform): diff --git a/Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py b/Deeploy/Targets/PULPOpen/Templates/DMASliceTemplate.py similarity index 100% rename from Deeploy/Targets/PULPOpen/Templates/SliceTemplate.py rename to Deeploy/Targets/PULPOpen/Templates/DMASliceTemplate.py diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py index 7f1c2e21c6..200ad1b9ea 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatAddTemplate.py @@ -6,14 +6,14 @@ referenceTemplate = NodeTemplate(""" // Add Parallel with 1x6 unrolling (Name: ${nodeName}, Op: ${nodeOp}) -int8_t ${nodeName}_core_id = pi_core_id(); -int8_t ${nodeName}_log2Core = log2(NUM_CORES); -int16_t ${nodeName}_chunk = (${size} >> ${nodeName}_log2Core) + ((${size} & (NUM_CORES-1))!=0); -int16_t ${nodeName}_chunk_start = MIN(${nodeName}_chunk*${nodeName}_core_id, ${size}); -int16_t ${nodeName}_chunk_stop = MIN(${nodeName}_chunk_start + ${nodeName}_chunk, ${size}); +uint8_t ${nodeName}_core_id = (uint8_t) pi_core_id(); +uint8_t ${nodeName}_log2Core = (uint8_t) log2(NUM_CORES); +uint32_t ${nodeName}_chunk = (${size} >> ${nodeName}_log2Core) + ((${size} & (NUM_CORES-1))!=0); +uint32_t ${nodeName}_chunk_start = (uint32_t) MIN(${nodeName}_chunk*${nodeName}_core_id, (uint32_t) ${size}); +uint32_t ${nodeName}_chunk_stop = (uint32_t) MIN(${nodeName}_chunk_start + ${nodeName}_chunk, (uint32_t) ${size}); uint32_t i = ${nodeName}_chunk_start; -for (; i+5 < ${nodeName}_chunk_stop; i+=6) { +for (; i + 5 < ${nodeName}_chunk_stop; i += 6) { ${data_out}[i] = ${data_in_1}[i] + ${data_in_2}[i]; ${data_out}[i+1] = ${data_in_1}[i+1] + ${data_in_2}[i+1]; ${data_out}[i+2] = ${data_in_1}[i+2] + ${data_in_2}[i+2]; diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py index 29a216d728..bfa893db94 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatConvTemplate.py @@ -18,9 +18,13 @@ def __init__(self, templateStr): def computeTransientBuffersSize( ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation) -> List[Tuple[str, Union[int, IntVar]]]: - im2col_dim = 4 * 8 * (operatorRepresentation['ch_im_in'] * operatorRepresentation['dim_kernel_x'] * - operatorRepresentation['dim_kernel_y']) + # Memory allocation for the im2col buffer can be dynamic, based on the number of cores. + im2col_dim = (operatorRepresentation["weight_type"].typeWidth // + 8) * operatorRepresentation["n_cores"] * operatorRepresentation[ + 'ch_im_in'] * operatorRepresentation['dim_kernel_x'] * operatorRepresentation['dim_kernel_y'] + im2col_name = operatorRepresentation['nodeName'] + "_buffer" + return [(im2col_name, im2col_dim)] def hoistTransientBuffers(self, ctxt: NetworkContext, @@ -34,6 +38,39 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, return ctxt, operatorRepresentation, [im2col_name] +class PULP2DFloatDWConvIm2ColTemplate(NodeTemplate): + + def __init__(self, templateStr): + super().__init__(templateStr) + + @staticmethod + def computeTransientBuffersSize( + ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation) -> List[Tuple[str, Union[int, IntVar]]]: + + # Memory allocation for the im2col buffer can be dynamic, based on the number of cores. + im2col_dim = (operatorRepresentation["weight_type"].typeWidth // 8) * operatorRepresentation[ + "n_cores"] * operatorRepresentation['dim_kernel_x'] * operatorRepresentation['dim_kernel_y'] + + im2col_name = operatorRepresentation['nodeName'] + "_buffer" + + return [(im2col_name, im2col_dim)] + + def hoistTransientBuffers(self, ctxt: NetworkContext, + operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict, List[str]]: + im2col_name, im2col_dim = PULP2DFloatDWConvIm2ColTemplate.computeTransientBuffersSize( + ctxt, operatorRepresentation)[0] + ctxt.hoistTransientBuffer(im2col_name, im2col_dim) + + # Manually set the type of the im2col buffer to match the input type, since it defaults to void for transient buffers + ctxt.lookup(im2col_name)._type.referencedType = ctxt.lookup( + operatorRepresentation['data_in'])._type.referencedType + + operatorRepresentation['ctxtBuffer'] = im2col_name + operatorRepresentation['ctxtBufferSize'] = im2col_dim + return ctxt, operatorRepresentation, [im2col_name] + + reference2DTemplate = NodeTemplate(""" // 2D FP Conv HWC with ChannelOut parallelism (Name: ${nodeName}, Op: ${nodeOp}) @@ -47,6 +84,7 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, ${weight}, ${ch_im_out}, ${dim_kernel_y}, ${dim_kernel_x}, ${stride_y}, ${stride_x}, + ${bias}, ${has_bias}, ref_${data_out}_${data_out}, ${padding_y_top}, ${padding_y_bottom}, ${padding_x_left}, ${padding_x_right} ); @@ -66,15 +104,48 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, for (uint32_t n=0; n<${batch}; ++n) { PULP_Conv2d_Im2Col_fp${data_in_type.referencedType.typeWidth}_fp${weight_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}_HWC( ref_${data_out}_${data_in}, - ${dim_im_in_y}, ${dim_im_in_x}, + ${dim_im_in_y}, ${ch_im_in}, ${weight}, ${ch_im_out}, - ${dim_kernel_y}, ${dim_kernel_x}, + ${dim_kernel_y}, + ${stride_x}, ${stride_y}, + ${bias}, ${has_bias}, + ref_${data_out}_${data_out}, + ${padding_y_top}, + ${padding_y_bottom}, + ${padding_x_left}, + ${padding_x_right}, + ${ctxtBuffer} + ); + + ref_${data_out}_${data_in} += ${ch_im_in} * ${dim_im_in_x} * ${dim_im_in_y}; + ref_${data_out}_${data_out} += ${ch_im_out} * ${dim_im_out_x} * ${dim_im_out_y}; +} +""") + +referenceDW2DIm2ColTemplate = PULP2DFloatDWConvIm2ColTemplate(""" +// 2D DW FP Conv HWC with Im2Col and ChannelOout parallelism (Name: ${nodeName}, Op: ${nodeOp}) + +${data_in_type.typeName} ref_${data_out}_${data_in} = ${data_in}; +${data_out_type.typeName} ref_${data_out}_${data_out} = ${data_out}; + +for (uint32_t n=0; n<${batch}; ++n) { + PULP_DW_Conv2d_Im2Col_fp${data_in_type.referencedType.typeWidth}_fp${weight_type.referencedType.typeWidth}_fp${data_out_type.referencedType.typeWidth}_HWC( + ref_${data_out}_${data_in}, + ${dim_im_in_x}, + ${dim_im_in_y}, + ${ch_im_in}, + ${weight}, + ${ch_im_out}, + ${dim_kernel_x}, + ${dim_kernel_y}, ${stride_x}, + ${stride_y}, + ${bias}, ${has_bias}, ref_${data_out}_${data_out}, ${padding_y_top}, ${padding_y_bottom}, @@ -86,4 +157,4 @@ def hoistTransientBuffers(self, ctxt: NetworkContext, ref_${data_out}_${data_in} += ${ch_im_in} * ${dim_im_in_x} * ${dim_im_in_y}; ref_${data_out}_${data_out} += ${ch_im_out} * ${dim_im_out_x} * ${dim_im_out_y}; } -""") \ No newline at end of file +""") diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py index f4c22b2c22..d007e60df0 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatGemmTemplate.py @@ -24,9 +24,18 @@ ${transB} ); + % if A_batched: ref_${data_out}_${A} += ${M} * ${N}; + % endif + + % if B_batched: ref_${data_out}_${B} += ${N} * ${O}; + % endif + + % if C_batched: ref_${data_out}_${C} += ${M} * ${O}; + % endif + ref_${data_out}_${data_out} += ${M} * ${O}; } """) \ No newline at end of file diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py index 11b7c9aa2a..3cdf26097b 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMatMulTemplate.py @@ -8,8 +8,18 @@ // Matmul with row parallelism (Name: ${nodeName}, Op: ${nodeOp}) for(uint32_t b=0; b<${batch}; b++) { + % if A_batched: ${A_type.typeName} batch_A = ${A} + b * ${M} * ${N}; + % else: + ${A_type.typeName} batch_A = ${A}; + % endif + + % if B_batched: ${B_type.typeName} batch_B = ${B} + b * ${N} * ${O}; + % else: + ${B_type.typeName} batch_B = ${B}; + % endif + ${data_out_type.typeName} batch_out = ${data_out} + b * ${M} * ${O}; PULP_MatMul_fp32_fp32_fp32_unroll1x7( diff --git a/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py b/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py index 2f202b24d2..ced6c3cbcf 100644 --- a/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/FloatMulTemplate.py @@ -7,11 +7,11 @@ referenceTemplate = NodeTemplate(""" // Float Mul with parallelism and 6x unrolling (Name: ${nodeName}, Op: ${nodeOp}) -int8_t ${nodeName}_core_id = pi_core_id(); -int8_t ${nodeName}_log2Core = log2(NUM_CORES); +uint32_t ${nodeName}_core_id = pi_core_id(); +uint32_t ${nodeName}_log2Core = (uint32_t) log2(NUM_CORES); uint32_t ${nodeName}_chunk = (${size} >> ${nodeName}_log2Core) + ((${size} & (NUM_CORES-1)) != 0); -uint32_t ${nodeName}_start = MIN(${nodeName}_chunk * ${nodeName}_core_id, ${size}); -uint32_t ${nodeName}_end = MIN(${nodeName}_start + ${nodeName}_chunk, ${size}); +uint32_t ${nodeName}_start = MIN(${nodeName}_chunk * ${nodeName}_core_id, (uint32_t) ${size}); +uint32_t ${nodeName}_end = MIN(${nodeName}_start + ${nodeName}_chunk, (uint32_t) ${size}); if (${nodeName}_start < ${nodeName}_end) { float32_t ${nodeName}_scalar = ${B}[0]; diff --git a/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py b/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py index 41c4b5366c..a795a555ed 100644 --- a/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py +++ b/Deeploy/Targets/PULPOpen/Templates/ReshapeTemplate.py @@ -25,10 +25,11 @@ from typing import Dict, List, Tuple -from Deeploy.DeeployTypes import NetworkContext, NodeTemplate, OperatorRepresentation +from Deeploy.DeeployTypes import NetworkContext, OperatorRepresentation, VariableBuffer +from Deeploy.Targets.Generic.Templates.ReshapeTemplate import _ReshapeTemplate as _GenericReshapeTemplate -class _ReshapeTemplate(NodeTemplate): +class _ReshapeTemplate(_GenericReshapeTemplate): def __init__(self, templateStr): super().__init__(templateStr) @@ -36,19 +37,18 @@ def __init__(self, templateStr): def alignToContext(self, ctxt: NetworkContext, operatorRepresentation: OperatorRepresentation) -> Tuple[NetworkContext, Dict, List[str]]: - # SCHEREMO: Selectively mark 'indices' dead, since we don't need them - if 'indices' in operatorRepresentation.keys(): - ctxt.globalObjects[operatorRepresentation['indices']]._deploy = False - ctxt.globalObjects[operatorRepresentation['indices']]._live = False + ctxt, operatorRepresentation, _ = super().alignToContext(ctxt, operatorRepresentation) - # Same for "shape" - if "shape" in operatorRepresentation.keys(): - ctxt.globalObjects[operatorRepresentation["shape"]]._deploy = False - ctxt.globalObjects[operatorRepresentation["shape"]]._live = False + # Get buffers + bufferIn = ctxt.lookup(operatorRepresentation['data_in']) + assert isinstance(bufferIn, VariableBuffer) - inBuffer = ctxt.lookup(operatorRepresentation['data_in']) - outBuffer = ctxt.lookup(operatorRepresentation['data_out']) - outBuffer._alias = inBuffer.name + bufferOut = ctxt.lookup(operatorRepresentation['data_out']) + assert isinstance(bufferOut, VariableBuffer) + + # HACK: Tiling wasn't updated in the Fix aliasing PR so we have to still + # set the _alias argument + bufferOut._alias = bufferIn.name return ctxt, operatorRepresentation, [] diff --git a/DeeployTest/Tests/testFloatReshapeWithSkipConnection/inputs.npz b/DeeployTest/Tests/testFloatReshapeWithSkipConnection/inputs.npz index a98a6c33b921b54fbb721accc4ee3ef68c4c1f65..36567a96ced4b5fa0b69b4cf85a84ccd38144d5e 100644 GIT binary patch literal 2996 zcmb_edr*^C7XN}gViqkcv_eZY>UIb=rhoxM;GO^iOGRl0i9(?j6lk!Nr$tf02o$Mh zm5Ps4QLv`A3t3DbzJPlYS9Wn-1|wS5?MrAQGRRbllwn%RZazplleB*|y~&v~_nYrG z_x{d3-|zn9@pGJ4FtcL`6Mg?q!T&5{F5|^y6cud>5akt=au^SW;aJ|YB~DKc{B^D-SiHB-I(a+*aw|GDgua*K;DYoC?Tq z%a<)ygvgHiI?*TmjbzJrEwVm!h-|gK2cGW=(Z}X1WRfkf>kUyu@ZFw9S>H)d!`(|7 z{j*{T4ES;l3)juX`>Wp24|J~9Kg!=sYbD2JnU%Zra+}h<{aI z;iUxRtvr%8FhSA}d(eL-$ABbtACj%Ej^0CE4*OvgyH+RF;J5JM~ zx;F{;&VH)d`5!WUFcU8P=m}n*-leCyJfT3citOY#K{eMGHCxNj{pLStLuxek%}<0o zJL*Zd=WQ}Ia+)v|2il!e;y_{wM*bsJ_;{NL<^3l~f1-}6ziuEqHY%v=`XrFIFU0+S z^Txq*-uQK7HkcZliN}T#NQhaF>IY>w9T$f$1`9Da;|95;xJXJaCc!qbGd5R=aPpQL zm>%`ev`tUJ=yVZ1Ubq0#@5f?W00%q08;E3AG8uoff;y?a;RiPnOlU&!XbTs6m0Mx_ zs+I~X&(pY1wqw=t1z6L)he-V0X!EU5j1U;Y^1c#bbwCPAC*5&yUOGl|mf_2Td!RrW zNqoCblI+erOj;^HuiR#8Sj;EYQ5l$d;tQG_<%7(rV5z(c>FDrZI{s9;0@W9v!`_s~ zu_5vtmCs*;6Yp&Rfi#{@M5TdlUn9|VC8NYY5U$;=rSjFCRJA7w<$KG~yX+7#oZCdx z6kUW_n23Fk0gMfYVcg9CIy#^rUjEKtYDs`5aSn`4t-+elRAfi!7nI5C?{GgUL#`+X zM5Zw8zR3mC!;eW*`dM=Q6&|{OsDudD3?gZpLx$hUz^ZTi2-E08qYn<#k#AB#w>Fbh zpP7e=hd8J@vAUykbUq|~T0w*UxB#_D=jhr98P=#T5S3pnggX@?|JG|HP38>B)=)C3 zxImdxF2JpEh0J0-k&mvV+{62*(fjjoqe)EF^=j&IW*Iba(txkO-XV#}qAIWau%^0g z9qFPHa&6~9QdOzMs<95*ePkmTin~bD<@gS6@{<_V=!-wdv#{25me$?Z5@FafP;VI_ zf;F4bH0Fc4<4dSSvmLybcoE~VD!RM(78!E7N^3uQ22KB!g0^Rf3jVx~mba8+qT*Rd z9*=}^bsMQu1)=u`yK!Rp1q>Mk$TfaX`f@kI247cLdt@(B74qAwby1kBNJXdOd^8=q zNd)OXQo-X1RG#FCMzxeyi^Lca>xWF=UkQJ?nu>Xgz&%n!J^merO0Ae0114#@rh!hK zFUD@^V^AUu!UHV~C^rldk9#3d{Zcf>JuLy1`xw18MM-Z?0oY2H%O4_+*h|++t8^JG z>TAu8N|z(LWtL#x2U|TTlk-zs-IZ5q?G**yKL0)W`_gj6kwwt@mJEzOMWEbYNckHR zaVRvK^uIa}4s@5JGEYf|U-z+7?Pg){`}WkuR_fLZ$C@3Y{ySVe(=I~2&pt1i?deG` zZ~w*J8EmD{WH~)+c8G%6a0EGae7x>US3#H7PqTO32FbfUgn#cL^@u4&-{lWLkbKmx zFX~i5{dpP3)%?@y` zW$$cK%{aoJ&7wVwwMJ|MvSAAgGXq)Jj8U?Ov37)Y8*JFZrY*1;b7Bu;rNCfbi49xW zW!Kr&W`w~W#(qY>zR6GAW??fQl|77Y-6r!&Y}l^0ojVJgX=HmC+ZODpvtbKMG*8)* Y%ruES-o?CUhH*3h_L@mQ&0}Z(2be|CQ~&?~ literal 3706004 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 ~$A5Uw|l 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

lo@581A+!wi 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

TrC(TMJCXCPtsh^DO+s~>L7cha1>T+4 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

ATt#*J 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�%jK2i>Jiov)oX-Y!$=(7u#<}K+yi4H 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

&RKNH^C3HeCt!O&T-p*XBjmf}G9mVUv zZP5K!F6?ragO*R_DE;&@E_xmSdu9}%=@&aNi5~)Uyo$@W8=<6dF(xtJO0h*QxSlm9 zYqoxe*TzCz!Dj;KYAuRqwf~@kSr5n^XHMS9!*EJUnPsrMu(0_ATr%E*YF%u16|f63 zj0!Mgr$3prl5r%YgJ}(O0IJwb!WZ%Opw`0-4Y7%%yx zQuf6IwabLLN(F=PK=A^Yxj(}wd)6&7b;Zevj&RD{gl2>#k80{{6F z2$ft9*+mrJ#J9sd_B!|955r&Uw}75?FL`z_32Q!0q&?&l{5et!F8NW=T=5e>FA2q% zz03>qu^sp8WstE`vmlV=yhq+#K)LDcnPMqUr^Wnb{+N7hW89>W;3&??)`{SBP7_>K z8)Lm{8jP4)p~7rQoXB#Vt8PhvTd^&!?a%|&hnXxV)4{mr#b}oq%X0PeL7<&|X!T!$ ztv%{E@Ujq2hd)$Ni54SI&014dUgrJ({qq(-0FQ8rA>Xi;I47lIq)Qx4(|{eSYxmNSoYT&Q6{oXM z+E5T~Da+ye%vw6tsuVU@52NL5W!TwZltJr7~N168|fO!nN4Ro;{)PrH8pM)&{R$i}HQU{#q5FVvdw!HF!pwv3z{ zPC-uGLDZECh1Pu~C{R2VcW}SqTmQv4VCoDnL>Z53)&%Z7)?wV-=ZAr>l4wcAQ!+us z3FM!zz|knx6dbySZJ!Eo#=k0vIaZ7=30*`_8DW*yU*6sC)Hme3A)0EQ8NA# zWNc$SfQYR)eSQzxbAO@EK@S+tmjlgF3#y_qhU)2p{8v6Nm>0Vad^Ce$)h8PqIX?(5 zZ5BXEW-cfE-gz)C702lB%cyZbm(1{ZjAaWMTc&$6=XHxBzJ0EZT;G*=Xm1o5wmJ%q zmmY)7g3oZsPZUc1(#Vts2jnPK;FTxx;4tP&{Bmo^%wvIYR#qLH_p4&}nQ`JdwiNw1 zA5oImjAkMd5YU{0=aWa#NT7hzmUJ0*PkliqoVyMY21R)7>{2-RYYrxtd?Z6>!?0p$ zA9%||!CUDfz}bJWKF1RtUl8G}NjJyGtKZ;b2lYK7G%ds&A2P1&-o-oV z;&+}HYx@UU>2%aHS7vztOOW||g6^EhGLHM)v9jqd?iQDU?SIoCx3~d9_sgPSV-SXU zXT!l+Kk;I52RhWdLYhb!9vS6>h^a8_Ok<3gGm7|EISG=3zoNoq8+cnMhobUQP$tIM zY~cQGuIwmFVslkCKK#X!2+=?y_pY(vkt3B-w!r zGSfg}On{sCgJu8O{lW2aBSxG0;dYh3Fwt=rDn$OGd~P-JSA@Y?*JMm7mS)@nw%gZ9 zq1wy0!%@j??EO;-x<^OA(exvp4!s7ejvAxot{&>Ra2^g?`Eg$D^#;e@b}C{=$@vOl z{_uv)cuu08h}amw75i1BU8D^5hNweBp(}Yhnh0C=XyL!MWU{b42K@d;P%E<{*nhJh z)N6h5wvsPA~s7baN64Gx&lRV@pc#-Y1S7%`5`EyVkXaJEN4eWgQ z7%OhHL;U$MPF0*Saa_TEzmKxC&&>}e&SCfYjI~(v2C(IB3q7~{2fT}!f~~XbA$&yv zYL$)glDRe@`uGY_sEme3k)Pngfew1}Vu4eb7 zQ*>?lTjUgmkzo9Xq3cahbe;>0G!-!})L)2hjU<0q4$%9^ZMeR)5pJYX{B9G=TdP*d zyC^mc=I=}4LVO|dxlK^m^*-r&W(4&Y%9vAoHh38gv5cW0H^5zptJoKT8=h_j(Wluc z{L=)_{+fXsSEOT`ZXV+{T!QBF0T3vB4Ca)&PQemzht2SXRKg)kF$fL*p5R3bG5?A~Fl|`) z0Tgna3HD@wtG^s>4i@5n&}smeXRY|cjKQwfV&wh*noJ25HUhxO6sV|Mg?lt^Y?SC8N1K;}erW#}0yfKWh)02P{B{&5Y|jb)Z9Y zI(}>WgxRufuv$h5JS}}mVZ82HgI-6xy&GjGP_d+t*5%x#|(E*Qc5?v z{AIJnPDnmKz;=i$$oJ}Scq)F6p7>>isLEWIBV7U#5-*`Wy1%U7io_- z#)SC;lTYEHXS>mCkumm01%UPI5a>2Gho?I;aCg*8u#PW9j|HQ6t<3|rntj0h17Vox z$9#|L_2B3FGZ2c8(9>!oetUJ4raJwkk1d?Z-|BMQUVoCB2;4%a#$fz_L!93aTrj*` z6Xul0;n{X+7@+>}CLjcNuN8%3`PS%jT95bE_9v0Lr~*0q`LL$E7S9E*fCZQB;eO3S z6scK)U5fUo{-+AupF826*x6`|>`UE=I+fa{Xzt1-la)=O=s^!;a<&mo?F!hY8_x;u z&xc5jrF2B@ByI@RLxCbklnF6|wD);r?!Ouky3D7os&k+&=qVQYf1;EA8Gy`S5$kGy zfv|(FSW$0@IfB_h)Q5PM;iV*mlLtHVljt;aPt3FRhwv6ZSpMz;G$*x#{$?}QSCoXM z7tRu&*QY^F^)f0AekK0}s591|5bYOTi0`susOC2<;-I@9j<>(0@nhTItc(}AlNb-0 zMw@VICl4HRt(lWi3XAnDaE7D=n-vt|_JlDUFm5CUUwyFaUMk2L2*S0|T70Zg3NgaJ zfLoS~=5MBg=zm4TUKR2FlYAVI-vHD6l)$ez5~Uv4^W0Rg;B_r!sA3tG#)WKVH%%T- zM){y%{|Q`tdL?`qEh3FFjUZmw1)k3pp=XmAp*3;vIi?CO)!t?E$y!{>OQ6={Ztx^b zghpSPN|ch{ahz&C!PG_4803-7}AxvxO# zRX)c+vjk*Xj>6Vc4VaK#is}i0kRJVkD%>@rL#ipD_Vp#K2pEBpGh2x}+Y>ySTSWXH zCZlbM3C2sFr0I*cJn&uHz}b5q4vz(eYPF~#t%Ho3Di|5SAZG};~Y3w9f#qEHH z3qzo{zXoNGf1}yQO=&Zmn+Wi;sj}Qj-d|Q*Yfc!QVR9WtJtFDR zTWdisb_K`LaTBDeHDdDOA2?Jn3i%u3!7BYHJ~Ot(BVp&^=~aaG{XrP5;R;`)Cu6t8 zEm(A@0&4C6KKWh-BWs(mMtT%2jo6Mu)&?qPUceE{qY$z?ix@~8rv-}7XosKyoo}#! z!~HuMt&U}((cw1Od2^api^xzz)ah4?KzbC@{-fmBrJbDK^^fln!)I?%>MuDWR5m^0oTalV!~3cPNG4$>l-k2 zq9hEI^TBWabF``GhU^J?)cIE&zL}WBGA~JBA^j0t*NxyV`3wxz>>{34-*MVYF-TbI z20L!ble`fk@g z19K|-AtTWg;x`>6lTEx}rm--$b6YfV8y}$!b`D^0kvR@LuVB`Sd-(X(MYP{qjt18G z^tYw}Js`P~Be829C*hwz@71CS{HWt>hP3S;lqRfz8H?7D@bOgKRGt7mO}TK0-S;Pz z`_prJALycCF3FyxLe&orp|{}zI3F&8m(Ed+ z`NEd4-uzp@0>UhtD+vcJmdrBAhMpr?_zaF%1WWgHu_h82M zjIu1V_#k;Lkbr7h*U7_;LxDJ1CKmMG>*zhNGDLn)8uh*l%k2YMgb|;wK6ac})6i?G&_~By@!|7un-c^hbCkt?=fIO`( zUPcBoT-dxskn7pD1pQ;ZKzE`Os*h%3-p54L4Y$DGH?8pXEMu~Ws*z7+qxksm3$!&3 z#osxtXlrgovXyEf*-(7 zk+B)?b|iqLY%6mj-h}pYTX^^6A>LggjK4RJlecWgqpw(vgfEFJMb}du`W4Lvb8y@F zcQ7)2F)CHbqU%LB&VLsLxLP}ro^Ch6>~|)Rm>>pt?5w;wD1Tp%PH{Y-NfnTPo@b5fo|ht+F<*7+cJUj=9Sj1`OKyn#wmgz{MB6^w*`Im?Lx+Lm1~s?0!8g zutuIiFoAVB~+Sh_^1(p>%=KdQrH>*KL zr8apY!ZNqaE2N=Pfz!E-|ue64N+s|;0$*5WaekWdV#&MYTln1ZtBkHY~GJ?hcb4@-{U zOq7W#+DE|<_J%$uG+WI>+%I7K>zEy>T@ zVT?~NO-@YaVP9h#$VbS+u?cx#aG(f+LT2Fh-z_M)qKWDcnqb|OZdl9MZeOm6!?s(A?aDJr#qyKTxcxMQI(py( zmVcVEVlGZ>aU;+BEJ@i}WT=TnEO){sxkni5egA!wDNV(Uy%jj#qX9Wf5;6D+^Ktwh zQrodwJ%e2^S3$JQbD;VVEkx}n4^2BE% zv=3ZlUQS7{xVfK*JN-aO);Cl)iKgpaHeemQ-?~SSlOMnMAZD0P99B$W`T5Tfbw7~j zD3$;zbHy<6`UI3TSOwFSKT+A2X4Kia_^Hzt-CSg`Z@DqbX;gvf^m1t2coPHJ&z#!$1EZQEn3^sU=6i>dG|gwY zbJPbPR=(nu&(j8hFHN+7IkLOEOnHa@c;WnMHYq)Ri(px59Zr{ji4B2=uqkI5S+V~B zv0i%;c#jN0V&`rm?zayYu-vb^SRrW;y2t)^40)TkQXG<)$oqKD0~OOX@bKo>FmJCq z#`^z7-eImGeV$e|7kEZ+k$UkE_l=BxyIoDup=xIdJWs}fH zG7;%>0W5P$0#|l#)F>aIJBk*7!N_7v`tS!!&=f+>S)j|_7u2FN9LMj*q2gdL+B|-R zTjG=O;)hlJY4ro-`HBQ=)f<5H z4K-B6%ml=bECJ2xS}M}^RC#quDgIh3h*8^}I1BO;v0xta4?r; zCcs~JY#}}K)db=qjIm%WfY_QbZj|#V>9H=P!>p4sP^QiEc2Fc*X`Ar%JvXv1D37{K z>_Xv__lfhaEjVp%Fb$}EjoMcu=vx1uxNedk^%J&)c+X5Q2zG*sIkg!3A{yuU@L)ZztDAuQ_3reKjd0QA_^uy=RFF$ zMUNeiA+scxz&2FJRoBxw=ki9dYD+BcS$YtCRHHFCb0W${je^(P9yH3dhCFw94*!=H z)JnXkE;2RP?b8O$m%dP=H>KE?5D&{O95AxD3biZDanFSSsP-M_{mSdX^psVwo-v2i z#=lTJ`UzYky-BlMKa7kMTzPg4KICLz;J7O8eVPUi_q_4&!Cqe9@z)r}&4rsGv%&Ua zFXYz>adn(+p`h9sTipA|%`zKomkX+tt8sEh2i}}vLQfiG(~Wh(U_U1soRv#4z&M@89-4?*p%gzAhd_^JA#g{F zagu2=z2z1N85hc+#wHOK>h$9DD`_bH+7Zs!AEtHhvpMzUtKpW5H}>x~K@$87W277y z$J`dI?d;)*l?OSz{WWn3w?Z$yxAcPEB@CEV&)o0#h}M}gdW>d*7DtY5waq})^InW! z@q>oRP2`D7Sm6jULcc}}$SGsz=oCNv(3wt`cD2CTrL6CB)fkdBWO@3Z%^*_ZRLVm= z8yZ$xh9CAOz(M{j^y}*d#n3*azh2?f3DuDPy#&?IwXyT|TzL9J0p5JDp-%!+ah75y znK+^eleT&DZg{_Bp7`|;eq;!$+!sS^<^;SQJdTE663Gj#5x7@v2Zxo7lecB^VPkU> z9#<3Q{*H1*s94YY>__qao?04QuT6c)4A2=4N#*6NsJnM>rCD2w&R|;n(ZYFmrhf+18y5JrBx>oAxIBbbczRWCoxJHxibf z%;Iqt9#GNEe8o7L4dBZc;6CoFquWlG!X?>jw7laRNGxpRJXqC-;$HWl#lw%POvwfR z{k25Gdlgila0PpvXqHj;M3?0SXm!X2T_^Uy0}}%t=YkMlZc7%u_^gJ^31z(_<-tKrbGH)5_UKoV0{0NP?|D8H!hio%|eVTz1p6(G{%70*EeWw^cQE`;n4qPh(RPf z<1UYT4@SuWkiOg;2V;`Rj<&l<8s4C)^*QW&^%(bOhC^A89WD863UYHtaewG3{1D=X zX3me$>G(EW4STVA%60GwEhlOo-8B460Zi{r!w{c-OgCEwr&8{qhSv!?_hcFlD5%4A zQFT1}ZWw3nlEG=a9>I;qAM}2}H`um49W#9Gh(wJgYG|LOoP00R#m>bGb%P-L^iSN% zy-aTw1aihM#q&B9`hkj>gPM#j%#U8kao^ERK6Fi>r#EZ!M(%llw?q_a7OWwkO=V#? z#DW@c=3|fk2cTZIaMM7B@tH+o>K*~^%$*sK&P#x6le!^IA|7m5{--S{ADXs?LPdK8 zyxjH=OSLR`N~_kB%{i5Hj*$n(9NY)K{#BUhTL3i{O)!>x1zt`31mDlyL|?z(*!EO` zNR>7dwHb~eonHprAxruqZUOPU@e#I|MxyNV^Q2jS8x+=!!ELs8jfwsQd#ClML?4v` zu}Ks7K^r`7ZG!9iYt@Bcdu ztR)2br{EkI#rwdkV#Z(-4}$1Lte0?@2RaioP)%zPzPqYZ`Tl+Mn-06*)=divZ;o*8n1Ad%N{5{K9}rTP)^RKIpBh&Z?Wd~H#lOU3nFQcV7;0+UV5^d7VL}w z@$l_<;mAsKP}_!IFYhMlIZN@6Qakorzs0t{QsA$hMJC&aK$lV<{Ea?~)kF6u4?LI_023w(avj~8iT2bQtbgbYg`rV6Kbhqn zZuFv)PczF8338v8*V1XD%jurca+I)iCNXL?sK)MEVKa*$u@CS?Ss4~+ox^Ps6Zj`s zAIjC^E__O8PBBzkO$Wlg=xQMiIMd|8xnbo@TIC;7Lxo;E`>7P(-fDmee0%0)vBEu# z6ef0-e0GlX-aiK&-` zO4JTMG`6ZLtIQ8%j^SPq@%AN>9<}7+x0mGO!e|)$k(zw>1#`Q7>7}=?b(3M1;n<)S zfyJK+L3#W+bnftkiSNJS%Jtfi+0~3SQ$0{A`Z0$8;X{i;DctT<1lh^4aI1{v3vHum zPQ?~ba)~6Xj84nBFpOS%bXH}-SUNsnUEq7y+CV(m8Uuvbe*JzK^GJ{2x6X9t>U4y2R?G=9 z>W5GCg!u<{gyY|5_9Ug}2=mp4z;Ul0Z2cz0PY^MIl=WqBZ*L)+k^i7$=`pDH=rYu49)SBUG~&K^f7uc=DYY-L3}bS1!v=rqw-!pZ|40s;4++sx;yj*yud_qlGf$Vz51 zqhZewS-c^Fy&b?Xa$b}zd{wg|InUu zZTfwf9{CsN$zKBA!45hp@*AEF?giiHkI3V3X^`+a1hyaIh+<$62*m6oZncMC^(|pA zba;;^G?L26Y05xE8$_)f49Ef4a58_9S;I{@Y!YsLHe1=wgS z$oLl7xYEKAtmm1-%-y0S^!QasJgyJ6(+{HZn@E(r>IFQrBj^+520Qp(;Dg_M@>`{6 zz!l|AZljtksaG^3LxtRITx(>)P)UUj9QgtR4qdNQKKE z)oISi0Ij{qbS|%_DD^lVUAE6g@mH*O<@!!yHSG_{OfIARftk=7Xuxgw+71UETcco- z9}&J84Gr6#5!m770s+lCKt@JS)rQ_=>KhEG_x_Y#<(@FrU#cF z>fwa3eI>3p_ADTH$D{N;=Vw-S|%Kvl|=XLRYy0`7{=s#%sHd! zLH0^LfvGD7(D^g_-c{YiMVtlL!F;3@p^mV12b;y`cc5b2Y{-o}OfT%W!zYK1K&4?C zcpO*6yiFr$6fc41`_JKb+c8Y9nhvAx>+z`kAUdAaMk{VGY-Jsc-A9YD>_H*477FrW zQxJvgK4ajKd1S@xeXuq563EnqK&DYDM3y*G>AUUN^Qsx$%YQ-j3J=^W$HVi_SCFEw ztz4y-rp)VQgp$saaQ2!FoH^@DpyTa3II!;(F6d=@F6Vsm=#vc2FPsOJyPwNm{TrOR zPwNawD_zCudWmR%CIVC4!ZBs0E;iquf=d>>0l#Z%q-vc$sd#Y%?oRrNjtw@D{Ll!-MFen8KXJk}hXtXcX)5;S?V+Ex4W~47-a?dz4knzs zMB1zk@xH_(PWq)k(6*=vyAR~x@)v0kuMtd~T{1x8dMLaTxdM&+6Yxsu1oP05S`tH z6?-aRL$MV~I`)C@#ogdN>_K{TPLRyEn^E`NApKE%8~k+7!+XBj5H0c@^(`rWwK{?~ zmzU$xC(AMEK@nU^(n!6nqldE=j-#ST8*a^83>m>*aDfcsf8Eh2BCrH*Ug^Np{Q~lO zY{r|pD<4AIPs6Y2x1o#e+G-6~V)6t(Z(!+W2)?)(ub8C*$Hfpe?7Ttg??D*8*Tc!w z{7tS*BVd*O@%@~@Ms&VeNLS2>=2u~iahVf@L=vh*Saf^e9?A8{D7?XxwlYPKn zopDBsMsRZ47|fj(i{hPWOoO(E^WiS|mF$Q5jS;ZtD*F|MCtzg58T=j?33tpw@#?8=Sd=tOzkk$+vPoxguJ&paJzPWm zi<#eH#Dsp+l7WN*8`##}4QDs%(aZhQNV>>ke4WwFOtTr|K{X?a>N9hP4~f*iZ3X4DWAM^>k}|Ie-=xghT!~f_0Y>Y-qPzI#s7Tc!>4&rL@ zNrdl5D9iCZ!^Vy#_^Ka5_P$sM&8sgH^DsI5p;`>OGlpbWs0nac4jzL>f5ZG+2Gqwp zf$We=!2FXhxSK7TS;jCK4#)kaCsr@OrzMfNt8fME$w))9Lz&Rr;0&ov9puw%Ygjrt zj61*eE<75)%sDgL2vx?i$fn78=wkH+A@u_~`1El@&)(y(QT3aOO+1P9a)qb=*JDPmo%!|N_!nw}-xbRGqP zW8%2AE(w1AO9Ho$O?Ya3Ifjg6!|h#+Md$e&N5(tx#L#qZ%PVJcPplkft6F2p;&g89 zrXV7|vL6GDbkR2C56Fdc=&o}{P|Cii2MdEy`@Ijj^q&x};}3%KZK-(03i0x*YU*@! z7{z>RfE;HWLxb12KISlS&ai=m9V?MIpJ(hK9gI>9LHYM~(0`YE zU3MT9){me>-WQ6h7|U)<8>R>l+_GYZtZ`ck_rsM?EMF8xL?kjG4c*~O_!9DQkq5kBvu1+Q zAULW%=2Qglghv~9qu$(H)*YwD^h{B_@*@c=Q$ON`x2?F{r5MsHgFyQ^4_`j=qxm93 z(0A<}w2%A+k~@L(Rz^a4SzW5<4G2#Dl~aM@*ZdL*`yeCSo!v5dA)m zGoo(Fy`|MkgumxtuX{VnHQ!C0JllzEa~I^Di(ZM}+-%W7Y7(67S&!Tham;y;gW_%Rxjeci2 zhn?hW^foplB%s^Pc09f-mPYh@;H*PD8qz;TYa9DuM&UciUbF^fhR?yl;$f=ZdzpLk z-~)UUI~&c)nD%%v9QgKa0dch&Tr;N!R@PppS-kBWVOWHo6A!?$hl_G8--*Cn8}MJU z3!ZJLhh%|Z@PKsOFS`ybnSS}ojPy_#g83RFdOfKyf`6&D?tkDMl@jWErrZ9qSO0>{Q>-6b?=mccK)waN@Ee_6x%+ZS*eJEP1yY~jI%5aevv#wf89L^kp>Cb8X)%l47f=V5Nx zZGHp2**87->s#FARSIQCgdkZ<8T9kn8NrthdpEa{%Box#P;G;q=i^94OadgR*#lRe zpO?kn(R5ROEWhN4pJsJH!Kw=QGg}>22@CQbJgY>J;CyV-x5Jf3|DtDMD$Y6;2>SwD z=;yfsbe{{Non|Av%!$JHEH~2DQb?tz43HpdiqAWW$;-Eg;pz0BIN<7tGD$UXF+7Ei z%1=k_ojt^{)*dr*?LoF!K>p;F1Q1@JhFo0%{BdIpE&+wG-(k=##_~rS`*C2a9&GSn z+RW7(czM!V%<}3*zlsMCa8?nXD+}=UDo5e$kxsI`$(eM{+eBA^lPTKr{P=x!*Ft_R;)7eW2zDg4^&3}+Lu$y^M%XpGgfAHfp6ADH%}6jmo`ql#2M zW9p59&Cq|~r~eDvKQz*L!im;9gH{ z-0qOdI;NyRE#(xZZXZIpsE!%gO_=WI(W z2;XOh;1{=YjL_@`*Q1{xPu~aToeH|Yp&x~70i94=k^^%j&vFh& z`jFF%TX1!1C7fW4y?XgMXxB4>n$MCkeMlb8W;HE7mIC*Iglti$*h;~`IPZxo+)sUhykGI? zl;%S-<>$b|7{>D`bH=TqRgk2=3#?sDLHGJX(qZy}?R=lYOHz(UOMk(R3njQw^D>q* z|9h29Dp^t60_t6TgkNeU$h%0B6xOLScf<%*uaZV{sH9q6jJ;A)M0TY5vG*tmc8YJt zmDitQubU;ghLw(dE!wRR9*`2x;m^i;=NZH*w3drE#M&0cL;PrCeitqleVw{rM}X&b+>Nvd z3(!}_xp*}r3Ke&#U|!HyFlubYhcCwIvF`@B?c#pSW?ugJg>5kWt^rO4h~cKn25c6r zz;81J$-rV;%n{p6t@!-0b(9ZuEpCzQtXFWP+Vj1WnHuVgx!{VFAq>g*haCHM5Vzh7 z7P|sqk?1|xysrb^OQ(arf+8%A6r-(*K`3Q#rV4+Q1lm0 zna1?TystDp+80x*9|MV&L8Ez1Xp>mYcuK44R5jMM4U<;e8d|6Vru_b=nX<{S9n!>ws#ft(d9F`e7{0L5~xbx@3_(-utHw zVuvE&w}&keKgD{Xi}c~7R_w;vd1P^#Zvq6@|Xn9#WIb%CO_}a<0vdp;QGeahxe5f_LZX zLaAg7y7{WG45A}_Jo!KP`$P#YL^gxw!dnpR`VuVmhJq2hBTQ%So13u*2HmUS8on!G zyK4`~H~j<)v%}y;=1)jlr3v!B1B@H@n3Kr%CSw(E!GFsz2*oYqUO41I6sP{hlikK- zm-=yXT2ci%^R{E))^lV9nF+rt@|iBmgUY!S41C(?*%gU&c)lw+V(tMyU&gckqxUF3 z)d{D?SE7&GUienB8`SyqV2;5sO8VEqXu@=?tGv#<-otDreMjOxc|yCVGG1`=A$xP} z@X;h&dVj+tUitE^G^Mg{!Ozix%ub4npg{7|aHqW54gC1}sbV z!}bF{MCtMvsLYI@G0T6@ASE7%P42@v4Y%-E$6Ays3E|q{2iVm42>(1R#T(U)u;|4j zygDZhwF8py#>qFR&ib8>g*4)QEd~5JIS0Z+N^p;RE*@z$#y+DOa#-UB(aVp9@+CcR zYSA%}G*;yDXDP#9bwN0>NJUP0_Z!@wvKH>UiBOjUmL*+a1OKVNM(g;wG-n0tnoLYf z<(u*ym3hoBX|E3l99lWtjJ^1hX<9?|1*ALt8y>jx7VOH?AvrNV#aXBXbLyhVgBhv7 z-7JOM-@SzH#?M$M=|ICf_;~_TwISho3VN8#L(^+kaDJg6xL95W(_dn=TQn0EJ&U7S z?yo_Sv7%;~41ld}H5ATYfbUm*Mw=CU@~dh*Vd*jZbG~8FMM+Q64hI`oEn7rvgg>33I*>NKPUms zP8Q&*8Y{Z(bthDk4m_Ii6wE71iMQHvqU3cOtL8EP&A1FGhVF%cGa67?^bYfFI>B(5 zokt&(xydPU(2{|$Z=M&9pVMQyRw7s`48emSXXLIHkpJ_k4T2JLk?*Vo+MNY#4GATh z&x+Z3{v0Ph+e3uW59}-~Kri=UDC&2G!x474ZZ#$8C8Q-*D< zbAHcmTdZ@-CdOLoke(NcqP%mk))t{GcrWf)6w7>ThMckr=4oB3&h=8CjD1?hXx^9$ zO_AqdzECS#wf(?1bG5*V*8{f#hBy|9y0G*G(-Z9ldC#MRuzulNmi2v!e-HYi>-t2z z@H7FZZ@mJoRon1U`$L#ye+II&Cvegoe%{{vXW+In1j4KW@aQJSX}bLog2GGD(G78+ zWQexq{l$C_Q|P=QKm$eBL4&9~XPQtMNY2{;cl26uj_eA?7Lx=w?YrCuP30uHknK_B zOW^J1op4fJ3)UL^MfXrHSt&9C`XTWsRK;eTtmU-q!4T8ll{tsggUH*l61d|Pg147u z!9!6VJ`ZKt9=Q?th?k~fh4wr+bDf{}4dY$_4k{I9Ts66Z3SRvkqQ22zvSjclOm| zb;o+N81}(0OJ~5%g+Z8K$o9cuUO4cf2Ne6(lM+!k?h8{%h*8P|(SKfeEnvF$~}G0J~1cV%HzWb2Y5OSgjJsOqE3=)r(wN$2IUkFh zLFug-ZtEC9$q0UM|Mnf1{91>p4$glPLY7QTgsGEMQ6|Qf zdM`DGlRd_erk{zML&xaewLeIk!gZ8+UId$``+zdri_eVX=bfq?!P6o)P^M4~%4dBb z=Czl=&FVGm_O*ibp+Wcp2-;fNlU7s8J@F+B+Ski~>Y6c-zat8UWh-!gdlX2V{)+GU zVnC9Q-L?G;LG*nz&N)*{USzA2w`|{YS%go%lSrX>o&ax8=SEDAi~$c1J21WO#`sg8 zsqF0lXiG6hp{0pv7T5jsy~|Hzt^AMtRLCrsab5`E1hK)u6> zYigJepKZS28|H;iiTa1COLgH*yBjQ%08Dq$#0ye2Fr=JA5C0w_MUV~VcY;y|RysoX zwQM}{*A*nc<-pZ}Ky+hTSi_}RWH87MGn}SD*#7Bchx7z4PLhW0GI?0Zy1E+gW#LW6 zU`TtfO2G7jDzxk01LJ%{cV;WGt_7_Yo}J8v_>CB58!d0etSb1(Kit zqB<)CzRR~A<8lYLy2{7s)-pWWuaYKL1s0_tRM}JV2y}{ho zcfY|i`={{dPC4hs_(S~TUjQ{+UwC?%!X^6~u%JK~ug)K%)d@q8`>_KYOJm5jAVCcJ zPnw+6zK!a-T-dpG7!+@^T+jAdaGo!lY@2?JyJ2_@7*r#zUfKbiE#7Du;)QB-3+}wD z0D6-TVM@|&Ji0d!GQ90!l-PsZp))YjnMAKoJcZj+WI+3F4;8Ufg2(rM!j1QiFeG6F zi&l@2s?%#AI_ey3FujDEvzo{k`I|5@^(bVhwqRF}4%3v!aQ2Pq^xEMLbedv~U0a*w z;QavJHmtzKJEO^{t^jXRI1dBD<3P5I@oi*Nx#8SaJaM`T)>d$_SJ)i+6$Lq_1AFn> zlRYr}g$HxJ*Pw4`3-?`B733twF}8CpY!!Y-mlR)vyWbp8Wa1ea^KC*Y!v<=cYKWda zYB=3L9iQ3hb1!$dLgIq6oc78excNvF^^O`qul_)M{G9FJF208fmB;vP^K!h#?~m6O zzeD-l5(Pvs)a()^6S zc4*?x(PH?PeVRjioET3q1fxI5fOC8k+!1hsIo7JA`%E-FAuNvnnRkF>?GZ9L_c1JF z=Um(LdN}c}A56g-)xXq%h%(CC$})H4NokYhez!@;LV-&aA*HI zQm@?ygn0?A9Uo(DR6I&$hvE&x&G6_f<2l#9!p-4x$hC|tR5({g{_F4{`UTb?vZxC! z!=7P*ojwR!-p8jsPE>Eml2gDk6($lp(NXR$PLB4$Che;b(md55TSk?=E=6xg<>?GO|DPua9JGhy&mLj7;0ru^ww=0=9~_g&C^FJg z2}`!}an|&uLTJ)3xaGG|wbSj8yz(sUQ(lfjX8jO$SwQ|-3}f&omEf|ggK)!390oSo zVH|rd#Yul~*ZWGaqpGkxXcj(-W^|k8=gbdng;f$=FgIu(1Z-%>6Bk-;0F#}cdBz_b>`=sH2 z)d4VF=Qr}j-X%{>K7n&;HaGJs2M6n>VoW{LzAePCyXHJTlH3lX;#Kgfd;`m2O~NgD zm0){m0=LgPP1+V&5f#xytUKrde09OFDJUMNJ}<=l)#9|KPzqxIZiVxsu4rLm4k;~# zc-YYcZyEdtJ`)NkJw5_0k$RByO%wJOq|*m8BG6S$2^yC0@qWs(GlAy|Rvv$Wb1Rw7cla%1Ao2CMCp<3NY^*Owv~)cxW@!)4Eg1y;!V&#)*1#}G{C+p zoAMuK+~lMyWT3hT))@KVNbfkLWWI!Bk|U6R{sz=bUdERqdgNYb6^<%=pv$l50xb5X zx32kN=^Z2FR0(3Q%uI;XY`};&-$B!{2{v%K^n^txLH0J-!mZyL)2t zk6N7nUnKOK)IztLGSS)EPITTqWga_Igx@>hLaa75=X&Dc^-px-oFDC9mqIo!5CjwL z0kG7iaMpiF~-A@uf-6nq)S&F`$o1UZ@|hw-?Y~E$2KAs*4yLKjHW$so;+B}Rc5=|ItT>*0Uf5VCM{;=kdKQ>P|vs?q>R&G9s zY5RcbnOu^y=m9iu^`SD0cHv-B1g<$h1JoIZ&@|5%z6kM9=;1F2i|D|+Gu7c`x`FN}5lE{p@04R-L{s|TMf zi((y!N)XEYO%5jmVe?QZ*VS_|)#BLNtd;2HQt|J5kX9IBZBo(sr^CD~wzJm2FWjOhKKKfWL#$^W|!tloo z6til>@a36k@$)cv-fG6^`e9-_!G}v8S70))i{u{Um$&@715VEDBCnImK+F9An5<2} zlK2};OG(7&G!3$0cQOtrTcM0g6mHu80;ib<;)XFk-VW)hsQOG3oD8?4AN#u(WVOJg zmJJ~M2 z0o3JP;hXYY`f9)yE2O7^2GeT)JQtMzbM*_%mAnYeKZJ;E*>2q7djr-kn!x3E-(Zk? zB2>I;4~hOFFxFY^WElY|PfFw`5aiI(7zeg&ZaYDxI|C}^$Bz-v7&wB@Zm95#LgCy(mD z$(8AFba69S992QL27B`RpAt&ESw|9v|B$TFTV$W*H(b5vJucDSh*qb{vANv?_iGzc zOR+@ADGh}!YbWrpO(4DgEQorT#bW{Uv$_=e&_~MAu;4pCZ7uW(wv_d}AIw88%QcUxu7I_o`>_($UzOJFV5zZ|8uj5P8F_& zhv&M`?pZ9JJ-iG}uh_us3-(~yJAetEPsm!8c2sBjOif%S5RpWb?3e^`!U^QSh7|H< zrGWf^|MJw$o+V&>?hxn;DUlTIKAa-M1#`wqx0{hq{~ls<@y{BfujWZVr0)lR|BI+S zZ5k(Mi#z9celuS3`NEhC;WW@vfX6S&7;T{rL}kk#a_5C1RsP;i#r;0x-wly+7J@RI z#H)w!zQ;FQ#NR4cTyh4geomnId~ulX=nUIrBgubte<6Cw33T}(!hPQw1GE0TN1eQ9 z`0Lsb*8XyWwA1BuQd}s#R6hm_?-Zi8Ml#JBy@4wt9pIy6HyWw=K%i^~rhH((k!di_ zpG{Gp?=v3ZyGZpnCc@S|1~{20!jM8SEq+)7*~inNOU0S~%HB_{hMvQ#IRhBUdxLb# z1lBw)gs@HS%s(3kKX1FkZihc$=7MlYkM(ubbwa?GX@u|cDs11=$Neqw6V6zt zvnCB{Tm~`4(h?`Dje%akLoBNOhqJ27@Mif-s1WppsZW|AVZaj4e`v(wuy`2qe}$Wl za>*R#$GW(C3YZ;#4rVJS$#30hL%;8?#mQzvuv_jS2rTOWp4?=3TPXo%KkVUs5D(iA zULwgIGvM;l%eZ~$Gu}|}N8Ys-keT`q^0`6=+3imEmagQ{)fs--2=Y(yb9+$V{-!E5SwhuqgTz#14oUnsm2l7$XsU4oJ zkj8iiiv7YbfwT?NAf2bMUM-E>-7^QL&wEX^MPlGmus!Y->_p`#r&LSfD#-WPfi;u( z_}q> z(~+R6GylRQ10@nr+s_ROe20P?rb5%(6uc2;g|S;AAaVbl)H#pr;GNAkSmQcO`Bo(o zM=yS!ZpLId$2Wm-N<%b1zz&Z0o`P4Uf!H-M6^_YhVT5QS=tlGN61z(vkC#shj4z=a z+uhjim!nN{1muOcX2GAD`!wxHCz=0q5Z$C~;iFyv{(Dl6M{@JPG-4C;!mvJx!v!FG zw4SbHY@C8!_Ne5LPes0(!$GH9IJTT+hYLLEN0}iwD#1nDJ~bG*nM8_DWrEW4#bjr7 z9BHp?ASbNCVEm6U2>T>)2Ar&*REpmXXo8KyL$vbrTo5`M!rg!2F>>z7al0f_p#*XA+SC+oc{nn64Q|B=m6 zp6IT)65bu^=C*F~BLCFK@Vi*9JqkFyGw5zv!~@Ejan}VQQ;3 z?vr9OFn=fP9NUDigzCY^_B8Wdyrh(IT&>=#LI3;;T)iZo``>;Em>*I{5C3V$y3Ns` zxi5z%?kK{0ZTE08>&z%w90i*80=%FLT`*0cgbQRZ9z2|i=PT1-b9gc5{#6OQd)F{y2WxKLyP%AIB|Togi@59@fq( z!mb7p?7kTf(thHYyJaS{&H4#9rAA@p!(LL`QcsSrR>beh9(cn{6E{VwqrQkQXjoom zEDQ%!Tc7}|xRE&P@^W;n`i^V&4}x!>DCp3&tY7{)KKvHJ=Jna+X=)XI(0k1lkjTNk zI~!3fD4quSHgFv8u^oZ24enBS1DpG|LXlq-(z0(8W^d(L5K2Ef#0p4^YB<+idB;Y*u{ooy3jEkGAl*Z-TP>K zH2c<{-h|pRU3jz92f{vHfQ5THVP&BL(go?D`k)-%RX;)ZejSm1LbjcQH2~Jv6EN+rC z;fSAdCNY^eXib|I{8sBnD&$YBr#7PdGbQ}u-G`!cF4O;Zzk}&lNqm zk2~ejZW36Nhm-#-gtc#dh@sU3vbyUk=oGNMUsEF{&Wc6Pnnc)hd>W>TiK3DX)8Azy zsCQvJy*K^|uU$OG9Zr8m{6<&7{#16OKPHO?P0KJ*z*|nDz7-x%t0C(z19qtT!&y2= z<(HJ9!qYoAvLGC((L0RY=m{spL@+>NlDtpTU5JZaO=aZ5VC?k=us9Qhk~^#5kYOI? zmbk#T(hi(G=n5%jdgQT?Af60ehm6_4HCKs*z92qKxm5yvlikovrx;of)&c+F3^0{l zg5MO*aC-&~@PVU8!_R4H@HwO(9bPZyl+Q82H)AQZ+T;y9TVIBkQgnF@JM=uCM$Tj-G2sHo3~&Rw-zpMD`mb16Og*|1C|-IP_whl%ld9E?!VKB zQA~?h_}xPjSWar2(iJ%IXA-n|=|G>0ELJr@h zyp@xA+leb3P{jHZn{d;sG%PQij1JWTaPv(tmP9-yx8l3-R6!xmT<3~DiNm;)?-K~z zV4lP;g;dd;-T9tTa9rMvpO{BNGmgz1S6#r-mrwrp&!5n2;SSAn*)DHC^LYGyi)iA7 zs)yb|h~gdSE^8-yJhEA@#Ai~YZistzix{KkC3yWbfUQ-!P`iNjk4sIW!d_n79xFF` zUOF9rxOcN`#TGDb|4n`@cEJg0Z)~bfhagJ_^tA24lpjyQr}_;z3;aWq$@}qR%1gR& z(oHBz)qt|j6r4ZpF}6SG!5`v}F}XJeb0c3v!?$MERhA1U3r3iSIup)^#SjtOe%f@{ z7KF0>NM?B-#%l$F)Vf#ned|Z){Sv{vkQq2K^9@{Y+`-PE1ayoW!izi2@L2dOS}FY< z{0v?}Uu_OJKMRBa>n7~1o*+?=uHtSDckmsTA_ww%A-m))+9*B3xDCH(lyL)C_6zbB zZ+{9?FMJ@DM=J5JU)d7Ph@F7pYxw1iP~ML1+IZo&iu7h=xdxl9{N>KJzBJP(Mb@f}w!>V!*uJQ&cXV4lj) z+i*M)%r2_Z$fxD9hMX2^dw`#J`cpri3vGZ0&EuH)aRt%R^?;%XInMSa*XfqW`H;+5V?Km5~i#0@i4@Pcv)&ND!hSmV{yXbz zvPb2bi#RuG8jiC)u!Bb@%3a@&A~RfA=iOsmWnGISlLh6idhPMdiMi+<@ew&|CUByM z`7&c&F!ZMbYz_E~QZwXOKgu{3{fWXS@A&`6DxcxNSUlT=iR_b|WW)TAcx|a5Ub)u` z-?%+cRhfsUPF$ls#&)Rjy&2X;T!n?LQNXq5fmwC|Rn~cea*O)7J5CM4kJEg-*e|0X zeNUR2uV)+<;|d}w^fc9IwFU&ZIDk^gG4MF1MfD6DFn`#CJG`s}di?6JsIQotGPN2H znW=J%w;hH^yIFE+`qgya3U8|1+=17{H6c6r6X(<-K3;`r9;)b0!g22$*ku$;0{wEC zFQf{m|CovaZwm1*pFVEGAh=s^g4MUGQ2VY0EM0#Zv@e;W?}91xmi;`e9#2OBrr9_> zumX9b5j=4s3*Q@l2gif}T-G&&s>u;7!-j-R7(iAj>!!ADBVW|AF>8i1^8+{H1;fvz zKrDkX*Q`)B>sC-FIf$M9 zVz?u8lr|eB;t~HGY!2qnsuqO}5)YfaHQ8xjzH05L;g!teJu{>}*K8jxl=Hc|1 zv*f`?Iqco)gBMmCquRPlc<7-ZZ+v?&Y|PvVvEaj%4k@J})mt#5paOr%WTk^p?mR?%wOLgo-~r;J7rkM_U$t@{m^CBTX3%{z~z}4RL|QXby-(4=9f!g^~Gl(a<~gxrw!8S z*(D%%#}lQ>eJQ8K8@l``z5lX;)5tiZTC%O^&TSVvt=4fM=G9Hi~;{W)?{jYDJEOK z#entx@T?~J1od>;=OUZ?j|JF&2>i@N;D2j|;PaNTGGPQ6M3 zqt(qQvC;^q<-8`rdI`9_wjX^ZeNa3`9gF)GVMrbyaz{M5*-Z^JF0}*9zsZ358$KTA zKrJkAibJv2ckvu!U|#sA4^R50!ufk=Ioo|p@#xWEtd0^REow($=jlAse69h{HkcsD z>A~cK&M0Qbe0>|LU|;ZREYkW6{B4(^@D+#3`{<*;Oe4AOUyp^8N5F*+4ZWr?tyg=jiztHT-0sJ+1 z2QDw=q%%+e7Z19DdOKk6csG& zZV`6Q3RoB@*r3=LnAjL79TL)_gmjlQJ7+;s0V$=VB&4J}#dqG1`o$lM`#dw}-1l{1 zVMaSBq-+LPZ6n$m6;0AI>g=}vta1zS%Q$XU3IIq5S5pyqEVwTe=gr4AGp^O=DIfbyJuk*K$L11~8r3KRFGqtH`-h_IZ;lO->}jORor8O7tUW>R8@wWw^W#w!X--=My_ z8aPYL#!0WcU?#hJ@gg!o^Ii@SrHe5xtOCF9oq%M$6{MsW;|6Dq`E(1ghM137)Wb&%Jg*zOH00_ACp6rso}K@-rEi=U2i#gMS$LJ|6X@ z25FCrKHS-G2$R(PnUgyT)?``2-QzQ1pS&ZyG~?r+R98B4Uq8ytOXCDq8Gy-%H3%Nc z0Pp5A*nRjjoUCT=&Tq|l=~xc>7rcS*?`3e|<0SGTGzF|!AMl}gKDKvuqtbuxShmU@ z>Xei4rJo@8w?{C#&lcpKEEndM*RDkOq?>4)wiX`D`o{Y4_1Gvj3m4hyWBT9QIMJhq zPG`G^yyjy3tgw=Kch@s+%@DMG+Q~8G*~&Q_&&8u@P9V#5hCBUZ$Vu4^&1dvs$BiBk zne0SMnzQ6TT{NWrwsT3wSwa3uwaw_KGDg~BPr~OlmGYiT0-@Shkh|{S8c?1iz;9T^ z7{JQ;(0z3U&g!znfR}5@z9awW&sZUDLx?$4>(o*kWWwUsp%9%P+?j$~liH2hi7gatee;+lCKES=nO@_fQ}JSM=h zI$+Q+isG}5;@_L=@b9h+C^_$ird`%3!tTXyr6NU(jV&*s~JmT@7W>n7n}j^?Nfzs4%gV|Z8Ci}@!6xqtj4VedRI`aDSlPv~>; z%ZL)lnZ5v}AAKOc_zCM9%93cFId0`8!Hem8aYXDN{!rk;@Z%3K?MgTn`IK=gbpA5G zx;1W}wvL z1^J=X>F}tc3m0i-LthwUmaP?pvEWCvWv?aNQ?thTKV&F(djYl;DUoZrPiVcN1H`8# z;Y#^%oB*5rO<+d%bWDrwEKB0P9~BYQ`WQzKI=T=w8O-sY;o zlhc3c&vsYz@ehOEj)xqZUs}H5Hx?TtK#%%)@JmpX_xg1cT9*XkXwgl~-`GOW?{dMESpyjH%n@G? zwtc=V(o*U^3i$E#+bP;CwLo-YLFpXP+~vjyIa z-@+!-$MV~Ye6T9{A57Of1*)xi^sGcF2DUsz9j`F(xc{BR8yLZak47{}F^GIrU5;|g z9uC=!;jl%llOd6I+10juM->cS*r+( z&xC`J?s*X3P>++tjPc#94pLV2A9~CaVT^7+=UOTc56V;!xvaCKX4e2Yu3m!* zBOWCB^Z@EE?cfQEtir0XpKv5JoW{-l2j;e+Q1#jhYqeit&WBsL=8rEsGfJ@i+EM)V zZvk?Yo1w$7k1FmuN9ArC;M^@`pyyzMuJ3kJX>9`(Df$jEtc$$waWAZ2eFs7(2ast- zTu{-AgiR4wP)=<%RuxEd-Xc=W5wCA<^kj9YG&z*`>UDTPhM zFA@ZJ=|cRjmr8WiX7=xFcmf4V4sdp$6C0&NiF#uxrndP2Y-SsXXX} z1<=%ODL7%P1*|kvfh%D>h#zKvhR0Uevu!F|byOw~EpB7EVK z;O*Wu)VzrU$&P(^(>aF-{6et(&kWAh3(&WY8Tj*k1Fc-ZoThqhxRAGq+RV#C6bb`} zGxN~*)&^W`ok6r96gTe|;y#dYfj?W9qpRab$e$yEN^|`vrz;Y+2}i($az3nH;)>-< zC_XID0Ub|8RA{zC#iSSLQTiKxPi@A%Wy+B2lLOH>3G}^ZGp}8C;_K^uI6>qVMu8HZ zb&+HlUtuCQvJdXCyQA{Ivlz3Z7-izCV5rgnMSGXSMS*fWBg#IP+Y@<#qqea4?n3;t zsDxJB&BT#gSBRdIFn6o?T|DG$PM|EAkSDAslSfgv$PA9$u)&{Gf?@llMD~9mAGms} zAZK$tmY58{a|&=6eDo66WqlaN-rVGgnpWW`J^m5Yt-B#! zL=8DCN0DJL#t9r=M#Dc0qqQ85{+O(ayLA1*IFEIzu2G)SwjeU|%n{NfIhnBwJh0@R z67AW>*eXhYIgg5~@l)t+I%`5WTvjZ@4L*Lj4u)|{z9R@L2=aTh1<2BVGjOA3cu|}W zey$_Ln}34yt)>S5P-}DyjUqi;8QU)D9^CgVLU_>!H*yU??qd?pKF;35e^}pmxP=~H zISu&>%gHg8xz3OHgfjUj@xYI3D7d^GdSc&0+qeqP`JN{>WfCC!J4nrf8$fD{oDs1WoNgG$V zBD)uC=k$XjuNXHnCeUV)cK9--nuZQ4z}9dlBBibY7DBBYuMAI2KHtuA<^^cp*$Pm( z5shUV!Lq=QXD8gssWjaN%gnXV(bxk6nqzSb_xF8xdjYH%V1aCAow~3LBJ9X zEREJgA%hLj;l#WtZ!0(>nb&dZS8+U}7K|@#Khl6VD)4W#7P_Tu=}H-Uu+LwNmTkUZ zJDbh61B}7qM-m(#TmlAz)5)$Wov?I56wiuf^#07Xf`772FyCSZ3N|sqfSIK})+V1$} zt3KNwjnnOOKhYC9&*;n9lQ;oj!sZC_!2RF={SrG^4l?=PQv5N|~Tr#hk8jMp*sA8034ZaFbv*b0L^QU2A2$G48>9 zI}L2vA;51HaK}SE8Thm|2nu$Tppaq$x5v(@I+T>@!8mWumlP1W$ z8ypHjuD@W9=N$S7`qapEfW?CYZHB^4-|8IGL&b$EGxDCMbzp#7T7_{=#8B+rKM;&<%C-I=8{ zx8p19pB)3@?kdo5QV-N$AArDwWf&RT48Ox$VO2apZ~kWT^mqyhG~5ABEoR`A{D*|+ z$H8%(4;W#hPF98oz_-tyz*YpHvWDWx$Ru>#_m1j*kD|S&*nE_|TT6aMp+#~%c~CM4 z?U%jjxw((w&M7gvN@WGksOpEJv#Ff*lR~K_;}|8R7K2!^EW~TXVM=H`$gt1m!C%SWUeA?HkC3#In0%A?iySbGB(1;@$nm#4XGLh7X3IQ!R6_FV#fepHd7l z5r*1JS+L$un7g>yk|-ZC#0Q1}93AOk4De_9tM$gvVQdA_>0!8Aq5z{x203@8^1x@U zKZtaO!qX;p#+?0(7yN?d7z=ISrC}U?_>si8C7;b58~8N`;81egg^ok^y?54zT^@KfKf_$gTH?1Zy*QG>&Zr1KBaCjWFdL`Sg%P zmJq;VM5b;NQE7COMrNx9&8*%593 znUL~t;W$A+pWY?g$cfR{NbE}FXRv3)8d=s){9MiRK4yl&xmz(-G!a+KT!!M4<)BY9 z5H&_;ftqIlp7B|Xshj#>y=)#>Xm;Z*ZXw8A|4t!iHO>qA&dXfX0ps4u5Sw}*ea!-B ztn?m`y<&@-(-tGw&@u7r?*CBXmL0Kuxrb~F^TUN9%88efUbFkLGGn~6#UknnW%w^^H9V{kZ0c|ZM8lAoeHOxlgQu#SFBB7Yey2?ghLvfmk z8I&aG(f7LpAo}aH#Au^i=;z0HJ{z?_V|_B#7`s77UTos(+dqjz!xEb4ZNYQN^FaAv zVg8U6g})aIsMB7+LmalJ^O;K`hJK)Pr2{H2NypO`*0?Ae=wrze^t~~Ku6>h0I%9s3 z({bTwC&Dt)RYFvARx9@2>cT9kHWb&fhqSk5SU=f>{yVgn&5Kf)gZC!<(horOF#)3I zz}$YngJGxlGZ2&*$A%T6s9BZ(c7~F4RzWKc8Kr^yNm=H-nuW@d1@OWAEd862k7L>F zXArsrK_{~Cl*QM(SLD1@`}COiMXg;xJT(8ZOqfYl0+xvTa01 z=L;Y+_aFMP?}&S5JbnCL3koEPaJtTQbRCSx))^vDkj%JkIv%*wz8ROMtUwvNYOs6z z2&89~VsYLGN9%MOk@upcWLOTDc>ly>*FIn;W6{Jt7=T{)TzG#f7`LsnM1Hd?ZVe9w zpU>v>w#6#u-}OfzfiP*`Fxaj8j+czfVapsFm~vK-TVg4Vjk&GlQCAnWJt{&6{)Lk{ zyN&`nZo?zBr_lXlI$quI9HIj!V#9+@$W!bf2W!jaM@4slV2>%Rd$kM`BivByO(DMh z848+iT-3T9j0YzKk{)9n#! zM}sW)@rC$QOL*Q_O+4k0q(qKTgZxui!e%DjBhBRMJ|S+}(lD6U6pQPw+0qO18_+De z7QHvELeAwF-hPW|;QKLzZZimij8-Ms|Ivq53&+#jvitB!ttR|juR^%XwnEnnb^Pi5 zkY36A3DzHH!iB#v^vaboIL#PDKF5Dh?IIIi`NwZq;_3hbI`-(km}M8+yWx^=478>8 zP{F=jSokBA7m=HRF5{H<({u^;-ROs-_g-OCUI=k)$% z?&X{>5PCiWPY8s=wK#y`eMQh%IRb@r^sc{>kg#oWR< zb9sKY@I%SZC^k3a3h+Fg!paO3_0dY^U3J0G-{Tb3(vU< zG+!bbwxpF}=(EQ($K*6_f3=Q0yZQ>g$WFnrl)oqvV#`r*Qv&r*!hDOUU2vay#g$YR z(d6Z=^hB5f;zUCf%XfzS+t%nM!e&_)bum?{jDA`B7xaEO;=+C#DCskRam|%*PKXCj zH|C?6V<}^`43N%ALj2DIL*$mT2P900#J{%r%l;%nFUXV_}PI4^*xc#+uLj zK`FI?T)WBV)r7fVL52&Y`tadP&^jC``ip83&rr(E73icqOm_<*rz{O&z1vL;-OOCw zP{F#{-Z<%z18gzfjXzEaa+AII^h0(&)Ov>EacLp`rnERRuSN(zI9$T{Ul^6cvzct$ zy_REO(SaUK!?gGQEsl;;4P0gXYLVxbXeaKB^<589Gvqzkmvs@H^fdbG-den{v<;rt zenZEP1-RD56KgtVz_f3>Vf98^P!}(USF2Buw*P8ivod2`1T#Bf7E z-*qD-6zBU8_-_x7^WL`+&&Hd;#A<-bnMEhqROA`H%M-HDt^XU?-CBeW;N+>kff zSgg;orV9O_^VuB4N}7QVvRuX8D$I~EAxqD1g}MHYB!YE*%>D}TRquU<^28e4uv`T# z4H|e{o4p{Uz6_ct#G}?3X&6|!7be(LqRu)#o;@}L_Z>Y7*V+AP$(Sh0o_-JK-^Q}O zkqvlh_@kl41;{R$40kpfBOZ8x5jQvEE)P9)d0Nj?VVN6Dljxcjjb4^NQ=L0dttMYA&8T^x*aGb>O+ax$s>%$VZ0i$MKt9k26l z2dZt&f(C)SdZ4oW> zNfV`tnVFb#*MNwxkbz|i>xjFi0Dq?VU(|i=g1Ji!Ag)q?`+dSNJgl{V63%8ibf*+! z7T*D->Hjci=PMjuCXZda8LRWP9te0ofaa!d=J!y+tEzo??Vb`y@_VV>;q$1f%ARw> ziJX^uA$aAq9h7cP#al-4ybxLnt0F&Bi4VQ_IPEzUO;kaPti?F%jxhg%86WZ&ErA;= z!??T>q|`~@SE3P`=>NvF5YHB!v@DltUM#c z_i$Ro&RWdin$m_H17axWZbBdboFs1@YX>KvWTD=#5u&!r1-WhApqE;Oj4i-i_f9yM z?XWgmE~4TERj3vB0zxlUKx9)rPS>ad``jG5`rB`E&YRs?e#E__i52YJ9Srr1W0Q!> zpfk`4uk#-8Ch)ysh3h}MW?vOLP0B(qCD!$vRg1gokCC1GJ#o@sJ8HS82F0|$;Fp;9 zD0$8bKGh~dOOQKmd2)lQj=I4L@6YfvS%dtU*#t%QyGdU33b2m1!yqx1i#(*vnY8;n z%vBBmv7|hd4QHQ`W+i+T-hx#ke<0`BE)+aUpi9jLFIuR=;F@nRJ3AQ#47^Y=t`$M~ zDBayw4y*Z}sie6(mDtX@jPp`)QRgNyQ#=D6WDJ7*J0C>VFsNpEJ~;zH{)(z4D0iqD zD(pFQ_wh{n)YpK1m8~PQcRqo+y()-ows&}?A5QNu#|LwAc+2{uP`zp#IJ*jALZ2*3 zeYfD`-#0+X0p_lL7LJ-pW4QCzJT%wH#?3~(SYN#f7R6K8(4NG*WL1m%KQyskMil(| zxQF*+&l^-aaRr(mmtu-h8#=%5qdr??P$j(_j=vp)M8Yx>-kJFFM=tQSw_tybCGU&` z#iV2As4?L;37jDh9}YLd4cT*WQ@9nT`8VOV_vWZ(?)V25jFv2tM6>w67_kFhdQ` z-MN6_*W>WvEY=rSks~vgj8fW^3s>|$;h;wrxVIY9@YWKDUmJ(NH9}!cp&@W?9HT{3 zkyOg4;e}x4nSUn0-K{H)M^5eMd~xrk|1HaA8E#Ls+SSPNI`<$bUlZIdJkX3~|1{5j z0cVwBaE=~A0oJz)@(+O1&q{r@UTpnUt`e$UzH|-P_;Kwn1R+9?K5q;2*yafjXmqKj+OT+M*TRZd4Oqc^x*pb6b1MYwJ&+1_zHls;(xiWa)z96fe7 zo0g~p7p1yrp&Mgo|41NwYbCI{>yyx^>P-4dSHRnl2sml*3B!-DxryLWm||6oZ#DeE zlX0_R?+QRf{d!tx$hu|{<{9!vmIxqDQR@wQW?DvznZPy>D zaoR`ihJ>N8PjX4&f&}C$++NZKQU}SPop+F!~T1pN%-kEFl5bo)QMks zPUEH!LSnJlJrxENOz;Zp3sj!)g>Q4CF7l_83Fai$<<>KoGc#e1>2?le4M`&?e4 z85x)(#Ldd?M2ERGNPljCWAkOuF6uR|Hq3y4l2~k%NJK3SeRj4VfVGSEp`pzmGX1GJ zzR4YiJyXi$C7lZ3T-$N7b-WY%v^{+6OX+7uG-+wHNd>8+-{*RoG8-j~ZPST!2 zW%wrAOE&HQND@LuC_mj1PrvqqRF!c!re{YQzv|1i?LEXPndXE~r5tfr`77p!bi>$V zw@@if7p*P&$N*^yUDr%9@VTnQm~sO6ru(pYl{q*)yp5~a?%CSI1j9I|;q5(JAenzb zyvGYqFaL|$7=_o=5%m`fgVsl3kaSDI?fW{>*0PJt)*m58Yx;0yVi$%r`oX&1L42~) z8@tY1uziIN-FUbIKOOmr(Dj<|Ok3D$m#Nw|f_Pi59Q}(^qigE#&2@hbP;TB#jUJ3>CM=(Y4 zB_zgGFgD+EI64?eZ|J_pXsJFp8VnNlk?lmTtO4 zcGwo64iP206xQRJoFzDYzYiw#mg8eFMcQXmOP5grZbxG;Tz7pAEjhy6GK|EVPaeQ5 z^IEzkF&o6L3}IzK3pUzb;Z-*+g$*bk{mg&+2&cy5t%iGe0*Aiv%?F)Ej1JJTfXDfflPRGHk|BPI{;#FN$4)dN0s$=p>1^% zShLT0e`yE?*%iTo*KQD+@eXarJkf#mq>4%cP{RHu1eskTt0XI6g>ePRG`@=2r#tDP z88100Vh3?+@HTv?G6dSu1h2OXK;+_D(Eei!^QN7_DWos7cj1e~ zHf#(o1Ff83D4%5kw)@hkO4KSWb7>>y%T*~{OMtsi;_%u^7dkF+6Jj~GSUAfIc4*my z{&~hIvi{55fQ1pHM-;=;BbC~VggW$*WA`+d)oG7_p7?L^_6&~cl&gGx+%g=ye(PX4mTowJ>A{mz?-&lWjQ ztHgR7pK1*sgIZy-dLC{!w*tK#`*6#=IC@9202&y7E3fSjg!x^9(Rs|X?k~u-?-k@P zc#=WG4*!F9R~zBK)&@Lu!UlF*H;}2qA8^F52Q(H@YTcg!g%Qngfb|~gt-YXy-RGO< zCGJ=a_uqP?CZd^Aqx(O#kRS;6^g-Fzi}n*htFs$zaMNe)Ih&3 z2j^-XqfuXr&{hU9Lg6;-Iwb(NZZlrG_<1@W=!`G=I^-t)+y_cW-a^3G4RZUtJ1nbv z!=7WEpdnETR=Q^R&FDXD{Az})Xg5@9xnY*O9Z`&*iaso7(sMllW;<9>@o5&Ik-ZS- zv5dWX-5zLL#Im`|&0v*B3)ub+FbV!%YQ|1_;nbBKlMQ?)fe=iX%)>dwnfgW93nJL6kgZuVwwF)h)LQ=C$8-S zhfjU5Dm#`gojQ|D%}xWog@))5Ym96Bko;SphF(+S;fC&Ea_v|Mbe?$y5pVm!eDDIe zJQCn{q{e`IhB$rm+y!Sz(#8#Sltp)pn7}L8{fZKn>8lBmhD`l?^zDQy@?~#jm?T965lPl&OE#jkBoFG?E zX`HhpNQi&K_cY|3ehPwnjOfYf7r=c|5lpl3!GaxkuzS598F+dM?w{uotBICqQ>#LH zNIQ0&dV$(qu}FEs+{Y5EzhrO%w>r+kfwy6BFDnNhhB>`Z#enTOq?}P1&g>P*m%|-!*zuDp1&HP zH$oU@f-4Drs)KviTjEB3InLJ$B|i#Y;9w9B+};hLsFw%so88I#NryP)msuu9_Zn)> zI8Xmx`N}DsvTr~FJHQNAC_nC=K(##jfX5(@`y+HKZ!F;qC154hM0Lwqnc%~nF zwBjJ?K>%jN3v)LIdEu#nfACUUfWNZj66tyJ1*XP^g8Q9~u**$~dEt0Ops1B>h&m@1 z_P~;)ra-W+gVmMhk7>zW2)dEp4ZTIHfNcNf0ukm?K$_!IknY^k{#V( z;hPVho$U7`djlY+501tZLW!^tIW4_~Opn#acjlsaez_40^Qv*-_qpiNkxIN)h+)G0 z3L3(8601r>IqjM8fX#_yoZ}6xGZ>?@?+AEa_rbG=8c6K4Ip96hgd?Wq1()pXKx)(k z+Lh8^*uf0i{Hn&d<-wQU8-7up^ic?XP1~(Nm*(^i|cZFHe-x^)ebN&NzvfHVu z>|weyF;@P_yAR04a&%p5z#LaXu>!ylw7kKZbx4v+fUEL*ei)J!-j`%EGJTN=M0RS zUXN7hJ#H%r#^|s^aGU*p($hQ9#AX%VJQV_0?^WTmPoF@O%|q`$6yidP5BcZ&2L0|% z0>zuZaPNvRG{8~fo1hP2JA@&tK_5kFAYMH9gEUNGJCWx%Ah5a>j=WcdmOmZfWSdFd zMzle3Nf_E$oI<-l!rWx{aI(+tAv_xILGL9G;hi3(v&zM>JktugFWkn)--EPpFd2hh zx}ZYqeGr+LMs;Ppz&X<}@j_}2wU}Q+=UDKe=%x)k&z6UIqYq2?fmpTn0|X?eK(6^H(Ty3U z0(zwo|Bs7}Z3B3n-9exAW|IAv55TxoGz5hUbHydj(ZXHkpb&kP(_g&=W1hVOBiSZw zYg$D$ibv6+sti;6Za#4x^;JU9!XTY!YHb%8 z-p;%Q8+YOnof{yv^9Clp>Vq?^8+C!PYgY!l;1up^xKWwHaX+vQAD$G2xdA?8-eqTA z;h7rn4&TVjubzxorlf=2@(6S^6X5^H_`ma%@?cRzExexWgYAkBQKr8ZTibF#rqTv~ zR2QO>c!R)&v^qPCY#^?xAxjv8VwrHh31oJbW$W6JM$uvvc< z;~VB-;>BlphB0a*hy1b6`zH+A+=76ZT9Q=|fKM)ehCl0y@WUh%OwlgJEuA|-DpDLh zy^djaS~hwHZULvECYTZO8YjeefSyDHJz3SjxjN3~5@!wKFN6x>VMkLKink=;sin}F zF#t}|>S!TQ&GL7D;c>km%z$+8suSSi?@@ab9vz1OWM zaCH;DX0Ef9$u*#}#0aw1*uh%0)AZ-PiHX-IM&S%P8->3(q3ALZer&Y@-hP`ziYRmC z2`*+_BQ_uSSqf6F)3F3qvF}_EPMML52g|MyhaXNTtZvU^8!7J8rW)Kdc{=2btI)r? zGjQxm3SzVn-~AM0d`0kSyIv?tzLJK2E%BgxMvW7`P8*aL6|nOrn>|R~Aqu}N(7HE^ z=Q!R3CSgNzQcjr=ERju)9j?G7U%Ie{{>4G~i-$_AAzxaM|Kjj(>QOpMS4^pcKsMX@ z(r_7`ei8-prjfMj|HJ8dXHj}2m80WPK!g>#iH_t~6gwRUtEVweoXS-&wz|qmvD;4{ znk8XBX~2zjs%-du6TZv7hkaN{dI`Q|^~>rfBY#neEnCkrucuLrDHGZ7A~{g*g> zPAa~O`G`4DI=CsK4;RS?^7`tc;K?)x;&b*FGzot}VV(tk*4h9{YkbI#-%^;a8j~RX z=O+Yxio!AG&1hLL7YmXzfXsBl)@H^9-{pnm`ZQ`2+5yjYQS{GB#L-x`XRU1_Ef)$w zx9k?yynjeGR0o0StX`07`^5VxB?h0a8$pepC!7X<`IY(yfX?TkuGL)3PAPzL?;^0* zKS4C4y7BA28e*%>!KjB-yqT;YIpKg4I*S=`-WN*KjcUcHS9+KT{j??0H$BMggd&_e zs{zt?j59afFr3V|2alHYfX>xOx;0r70$#rWZ`MuXRtRB~?Ll-5YQ#HVZE&sZY&iOk z;v<&V+Ih7aK6Ev}UR8gXX~yO>4&C_h3B{0@OfqM12drLvh;9%=`d_9#nuHysBjYi! zvl8%@t23u>i9HJG65zAU*DlWU}HTVgpY73DS%`Kp-Q;g>v*!wKSknxB+ z*j_&so|P4nM|Gw+@^(3Ptrx?SR};`NWijNZxkFs(bk->f!_5W$bnJ&E{0LagFnDk1 z6aPTa5(vfxWwAJ^E)B&C4zmud1ek_?hR(}@pi`5Dd>KAm+FS*xUHatu!;5%9$uDuE zwLTik=%B>4B%+@uz|X%Gi|=oKLp9e?9JH0f*pnuxoNq#RPO^p{dX9KgjWO_zOu;QW z59MCukrm|`u+V7;*0&x2*H680UaSeC&UO-MRUecJv4i$%U#!_@4?(J1poYEE6kfWb zHr)pkbu;P8yM{dd-tQZVH_+k2qI(qF}FlsfYk>_zN%l66w^#ba6oE4K%Dw=U;Y*IKyj+baS z#~*v@+c>%DKfq5@h#U29Hjdv=hn~nVaPh8!1C#Ta1N|UImL;<;%TMqT8i27`ws5S_ zgI;a(!`3xJsI#XYCZF`iT|6&%`8I&lCy~uNz)eKE>6dT{d*9u1uK>{W0Of!Lkl!%K z(|o!SbY-K!?%^cZWx;qeofY`HzYSv#xX>OU)<+BZgc7p3Q1+OT_`<8m%L~GJ-`}8W zSupL*6y}cdTR0o1hLI;zH^ZUJ^|Zg=8Tx;gW8OI%`c>W@U#!c)-apJQBVCCz>_VaQ zEYer|WU+bjWt5ze0u#zAq2uckEc|VOLX3y_6pTTMbucGA_zO7w0cr2ANA=TdIrg3N z;nc-4yz#0Xu1k->3gsYBAJrml3!BI#*4=-pf0vf<BG!As&O z<9=EZW#wPE^*|Hdi#}p863`Mi=tn*UR0FP$6z~aM!u+%LA z+g+_lMW+%@GVr2V7yNOXzce@ozk}>eerP!)NX^!~fKJA1af>a4O#K}AKBXDYKVJ^t z8mwTnb0$8Bf6QBRPn!-*4UFYy zp>NezoRn7#O;2BuTSdb7^3_Cq)Lej5%?;uBB_r4@nF57dX2NFfXZ+wEhhLs(@ahA< zL2UOB&bSqW{==`xoAiZHn8|v>zm;)3rx3yy2BrJ#(29G$N00SApA%kJyGw7BHCL)Rc!<+{e~E0U@Cl8KL$dtx5&A; zv5DkKOV0W&{#4H09?J$1PWZ5U>VY3fW7-(^T!c5|WC-(#9~v6}rbU}3gYISxnAk;e z+E5Z)ZIeTtk46~lCd@DYXA6fH8<5+VJxFFY<7p7qp*c zCQiPK^g=-mUN!PZGwF4(#o+~Y@TvgLUPGSs_FVXQag;8VDnpyUo-p~i1$>&HiW7!h zLGe8Sh3pvoU7T2BL zb%-v+I#k`5Ob!cLGw`EHFzWfY!+|Y-BBa*meb2Kq4eTI)+-;w{C^KdRd4q_Qo|MQGbJSpwtAl`1m`5n;6 z+ne+i1r6DJPD2DU-+qL9E=Hua(FGsy#PM{t7<6pfjQLmFuw`93Sr)Sgm-sD*wdRhX z_e8v`@3TeN5Fu2g6a0};P-%?A_MhER`O5g5&4X*Lw%TMtd0KFVN@{Z7+&l9 z3`2+RV{4=!caB*rkWwvZO?2lSds#|9x#wczur^%%+y?Jo&jhJ8VVHS_GoRbTr-IQOQC&>!>uZ#5IQ6wi{!q#8KG!!4|ivazWshHcZ{N71}lG@!i2Mm?HHN zPjlo!duIe#w5&q)Xan*%L4>i}h!8XLaG*%q^%(>WR^cm7wvEc^YP> z;*gU7-F`+D4qj@+Z-;y6?NeFU)R6;kYSbauQXQk-et;-nc1}7I1A(pvs5wayj(?eo z4t1`)aFKKrZ>-5EIj_Ng}{txEy7`VP1oREMu;m7}Cl9!$UJ zOL?Iq(8JRueJxeI6y>f&xg~D$-pP45?XWF-cCtRCfdtL6Zv)$J#yH2Bpyi~KAb3HL z+n@0V?``}GjtZ;jp&%jbN#arFLIs}%8br5;aavu&fJNGvTf`E!{rZ7ZyI2S8r8P{r z(0~iPb0Pd{4&Ah(7)~A!B2mXXP)x#;h<*qK_%I)*@Vju!?9VJG7OHp?B{=+<4*{ePvQZx$h_9`<*Q?Ap^1EY!m6bTY*&M9yS(-Ql<6*lE2g* zGQKSI)yfC4ul)@;f}~4a8b$K`>4I zjc!Lb&>-i;gk}3QP~&qCUX6^z@82vrL5e@|)`T*ccljpdUdbl)U6tt6^#U_Z{jp+G zF)cFOkD9xM!BYJTE-?}0Pq|o!cUEkG^RMHf?KR6gja`L{q1E)#xmq&tSO#jP32d|c zmH6|*B^(TQ!-MMS#IU0hGl$JF!ayFs#yS#n2?^>^H-=l+$AQouVXlgV7mf56;`_A< zaIZMF;49%w@G<;I+XJq^;J-5D&G`Xa2Xych#|3XJdj%oyNAOZY04jSJAX%h^6GKAK zapM%KeM^A9|GPB|WZB~z&qi2#%am{rS&`$veX(nL3M{;HA979l(bN1Vd9pr(+8xnO zJQ%eC{VqhZhs$-yxL$|fMZckOwk&Q@GC)N|mccN$!1>3%fWhrmIQ{ZZ#shaG_w!8X z(Pm8?u|1AP$A6&~UmaFo;lqzPd*Rm{EwaM$8qDlI2zoEyq6!*9g+drr_#FXTTzWZM zF8YxdF{T)haUH^v?TDA8KmPeQ1uMgjaMUkt!5RTBSlX(#rYit(Fry{iww4 zF{e>CISJa!wvh8)B_!9-3w=1gxH@qhCbKNuqy`~w{%c9Rts@5NMn&*Nc^vo$nc0?S<;oVJW5y^Jh(HkJYAqQJDXVClY=W(Z5DDQ&! zMpUR*gpx*knA=_sd4nCG%;vr88;_tsD|3`y6~#HX_@KbtWx*!|v3D!QWADOn&@2GM zWai;k5pUdE0xRQJ;+`Y8C0%ufwpWX7VjZ5B;asq0`q0TI{$A z-{r;Oe({(@!7pB<^6^TVYiWU(z6o>hLp?)(fXWwqhhU{x9CZ`q57_0y zjxB$oJSi6I6wlCOLp*$Nr}uvpoo67{-y6oQ1_|vUiT0$;b8e+%G-xR_MI}l~`4oBhSV^Mf=wkBx^zsWT+?1$c(-!Q}a1zy(za`p5ep8xP3 z8&4@x#f&B7=gwu|UTlM15nQ6}VMV_+2jQTl3Ot&k$5rfkO}qcbpoa7{a$(9C=1G*m zmgR!Huj~1FDai>mV#ijxqxK+ubEFj&+2L_jmNPy$upBJTQ>@Wz{uh+{@)EL|_rmHZ4qSZpgxm_-L$>VsfFHU3aK}ZT(!~>0 zTJ;}&v~U3?N3eP6zzU-OpF6mlci>jz-Ei@mA{LhnqSiJZ4zFO(#4_+w2VCxU!drLmz`*>2VB`^kmyDC)&(vy&URMlX(gk>jS(nr- zd@5%K3_`*0WVC-#1Yz@raQ~eeaI^c#eB)M}a-(tVjw+^cf@R>a#*yBiQ3@tp9}MqM zf@=q!(!I-Gpr^hi-2Lds^4y>CuR#vn)*ZwC?r01+ZHu>VbmL;}b9im3A#|L`!B=wm zG}X$9xfmVcw^=YWF1JFTe?LJmlON*SqhXXeQ5p;^KrN=7$gWC2z3x>Q(Ci3&PgP(= zdOr7Di~>!$`T_FVccbsf7m^=ah7Si5Kr+q+P>MO_kx+5KdWChJFDt%QRt$I4^A<#S#VD0lfT>V!wY z40&O^>$@4o+Dp)6@Hoz&R70G(PbgUz4D*L$@l;I--1QT}oBIWL<11xpg6nhKDfNXL z&vS>k75pIGR1JU52cxY`60C4o2MHH;QLpR>?7o#rCD=XDMC?~Q=i3USzmLP_3%_CR z^NVoCULPKA7=RZ-y|6?>j?>2OnvdkA;PcyQC>|1sN!X0@EB2?_d&}Vor5;qDnagR6 z8;4H*dThvE1WK3KJ%=wPSuQ!CaA4oI&Y97bFRbDE%@)jSEQW(cft;I0A?)Xe@Ws7oQt>DsX4<;rm)d-|vv3#> zWg3Dx%W>UJ&c`u;7*uAUSVl% zCT{e|#f8ohxOnUUgqS|%+`AqFLcVX{ujD;kcw-UW6TcHO*muu6^(t7_@*F3L#=;K? z36yeT&hyi=@!_lj_`>mm=l*?YQ1}@JoC=X7eHyWgZx)nTr9=Lg0C@2-LJ=(OHX+=Oc6u zdoR8x`%g3y@7;mW5oCy+A^Kn|TZCJ_*;AS6?zo`hD~6hd<8|eGu&C!DI*6RY0$UGA z^k+v3vq0Rty%dl7AElO2a`3k0Esk{j#pZ*@soDYN`Q<3!qjxr>JMb*KD`(w-NsRmV z-A(Zn^Je|qdRO6eOFkzeLqO^35s}n}_lI!Zp##|PAqejKhC(c39Uk5@hQp;jsG|7} zqt`d!<6G@`bJP=8N4;VhfeKg~KL@Uc%|g46(HtX%1HfJSf#_-GlgoP(@WGr8T2;0b zFU(cJZ>kHRMzRt$isL}_njISP3Gp;O2`c$`yyUEmTgF_rPQ>F$FaD1BKy-@p@L^s! zWsyGUU+jjjXbkM_aK+JwFY)%sU$i-~4iAhz;kNv9L~Ad`C4Ojve6o?)>uv?tES>3R z0rq_FDxf8AtnsqjA-MIYhxxOnqeRXSd=-3vavQEv(=Y+0?xLS?qj)38ze~cgF+-SK z{xn7GvLTq}3xKaoJa&yy=vXHPSr;Zq$ajR^dDDn)pDnp;wgFwHtmhn!5LD{C{2yKz zYNm4!N|8q|KjSKqKJbj$ipA`GBR=U4>W+k9nO!35mCc4#**{@3XB0e~QgILCEM8La zrAv*2V7uWo78rO=YEGrF-F_+#2`bZT{$k)PXMxHSml(Tk1fRYU#OB{S@htyKxHQKZ zZkvaqr0rw!_i+JK3rJ)7m2_Oc$&b2D`j_e%B7}F@oM|&p1g51LfX@~OYPj|~i2U~) z6Q{P5^}+REzkC>S7TBSEnhRr^vik)#6IA4N(rIis8Gmi8@O2^%LLPmES(V3$)0cjT zm@=3AyZw^rO?Ji~FQ?!V{~#*2<~4bqV>zU{>H}CQ`B6*N zIbf0A&3r$n;gZ1=RivfoYtj8}W~1Dzq0 zPj%u8ZGX%yM{(0&JZY^DOvrsDh88`!%zWt?UmOn|ueo<7bJPY%rKGJDpY@dq$@cL&m z$iWa;R#t%W>Oz<(knit>**!*u2CDP)TP4f zf)+aV^dKXI1cgVUjE@jP_V7m%10M4n2n52Y(NU;&@eh4j9!>Q`73`3Y z;a=Gvg}jPZVzj3fID>}R;(rh3E&l*Qol&s7hvk&oW-x}QEoil$f)bt0;CGUpRZ`Ev zUHNE`%l&~nPhEnSEBSdl)y;8EOd1V4W5u5P5tQA}rWjcn~2@uzR(nNkT>p?7d14sM$lo)@AwAqZJZdEqq_Q#-$y$u}qkENNM zpQtg+Iufciuwa2U`h9-_Hf%q-bI~w+9<2eCoIYCS8W`LE;qs-^eJ_x@m1=tv1r52FKJyK`26Q{9KW{@uUX|QZU_&8ORH9s?|hXca&rXsL{zcQ(iz4c z8A07qVOZJkgS~!Hc);le_JcRBAFo2)qbJBdJ2kS&#sWgd4#Ce0*PxU6IyIdyqx0-D zoXRK(+#ltDxf~y;Hkw9HY)V3osyrFauB**t)OaU^ z%XgyMkzF+0Umd5cbAtEw7a@B?2$<)rfQl1kL}-aJ8W3w@Gg^qR7OmnssU~CP^>`R$ z_eL{v350}S#3f@f^j=#kiJAEvBOkfpgWN_)C=P{NmjD%1_kvtB%Vpksfd*^6G2w|g zu4CQFXGz^;!|}Z!c(a&?peZ?(rui)D3b~xn6_S)P?pwh8u zI7bqNcV=+TEOi5yv#$ZnV^J)ZoGqRgHW7w>lpdGw*)@vOMsyPa;~Rpg0JHjoZi0z zyi}f1y_5UMz#2uo_LIF2UNQE`hbJWI&pp=RKTps1gkr|I2&jv3z@+mzj7?lZ)gGA> z7sHt(cd!q;Z}@O|uIph)^&<3|?&xyplH=x(!MYlKWLOixvqcE!YaF8{!@2P9 zNFn-VAHsK9{={dZjFz4_0#BH0I&dTf+yDK>TcND?8G9QKE-3-;#9j!RegkUv`{Kc1 zDF~YDii17<-YUo77;@A$I<{WD8S0OUU8idC>QI9Ms(gK+5bi zHWV=CmVXw?&h?~M!eU{^lV@;Ep`9q7sK*apo}5O@AUOLl0IK9`z{Ip4Bse@W;Da>Q);n6e+%9j`UGp({nq-nOHigb z7ezA1NutLDNH}i7)~$j{9~zTz)LH@8-LAoZ(fX|0#pZWkE2!~I#E0wGqms)WXjRV! z`BW9W8zBbW%X*9Mc2pKjxu}UwogD0Eo~whJbHEJ4(7ZDfL+}128XI1NHUx4% zhWx{@ENPhhs|wWrpOHFv<^NBlL zP)7au|B@*l2F%T452fp0r(Su_Sj?MiC|6_<1d>hBeoim0&{{@}*`4+H+e2+`0_pof8m0#QWv$c6_ce6p-yQR z?bz%^cHfC$9_RTG_If*Q*lvbXuLh%ew>`<<@`u=MZ$+t?SHxi93tS-co3S{{$s&nM zFej%F6U^+$_LHLY@vcP>zV#L1#CmLB?0*a3PV110@x(MO{hpZko0su#PH z3aW^wr#719#3V@vj~mY?%jb);?xG`cSY8eHBH25y z#2*^dX5w!5c;wj(f@gTz9a=Hv0sUljP&I0-4+Np_VCl&nrkfHhuWLkV9vjMIFRubS5zGUXWg}E7u`We64rsi(0&wGb4K2+ z0Lc1SO*dMx&K*)UJ{@BIp$;jYI^Lr7q#}+1osF1L?yZlD_4inx6vPQ zu%r_{4lvGPpfLO}V`qs2>R|AAKKgxbfqTE|Nv{7ZT-MwV%lUHfnNTdo-CO~04-}KM zGGF$cbrv)A1UY}TtQZqN9^5p}gZT0au5ia`*upvsyLE0rxZOT<+aiLyk|rR=>?7rx z?!fZ)GSKq(z$Gt3Vf~4G_$=uThGj26RD2%|vkoNL(s_9ES^%ExwuORCmzg&%7B5-7 zhU}44;%;yTy~N$Q`$etkmQVkn()26*?eoV!V@v2mmcj6@o5%K4+wkh8dGM-02KYYK zVa}@#5Wi~*0|(Oa$we2OW7r30*9j?ES8sr80iz)Aa~jv~nMT?c+rrx%6BO;;12^h^ zk_+$p(2&8Z-r7IMjaMtk^M4e28pGi7vM9Lps~E{jJN(>z3cb>fQrk5uEB=3TMoHVE43foY0OzMF&;lkP$-c?>=wRg(L+OqcGmq+|)U|Oz z@GPCV!L6jx@WeQbJe&`MI(zUxg%L8t`Mmb6S0KCsY*JbGNy@!Ok_sU?y*i z!wEx_f8i%wY$>Rezc`ovHgv!_Z}^m?bTm<3p#rC=_JLkOAV}4C!AXM&5Vl+h=UMj4 zN_7wCV&P+qNl&G^OCMs)em-7OQ#)t``M|V;jPdJI2`=Y+VD42Jh#IqJ@9s+Mb&P_l z#BJa?b|32vS@u(9AMBOuMk5_vZv4kEaE^(9qY_%MUUmXLju>+G-H}D_GB?nD+eFsS zA4R{Kzo;d;6hmE~gUDRwQkeG#SG`1T(Gh;7Gpj4HE$0R9+MWVGul*xGc6X*K1~AuM z6PJ7HGeEdN6gTSBSFjl<0S#X_TI|63A&sq=c|IFNT^r#+(lgw~(FV?N9Iblmz@4Ua zofGMpNNs}od1jT_us}l?Mc*z0g_ow#yTcLNSRXU(S|loqj=*KpOH}miNxT~$#+6n4 z0RKhp#mHE7dgkM9+94H=;}2pm{zwHJmiEND-2J#}+!@TO0-@#I7T93Km`e{>9zo0p zj)lI0Eyn{$%FIaMd;SOovcE&z35`^XoL0EHA{rL2Ey9C~-8c=$LvYi)y?7$Gm(Do3 z0+#%{!1_CP@$3shrH0vjO8PP`AQt=;4}?p>1#v617Py0g&EnucG>2=>ivy2u+u)aC zFeC(-!4(?;9*I0klJ}(HjQN((;5h_`wbx_UY$0?%YNI&sT{vK2MXWzq z60MZmkgFO2JRdjIUMf!Gm$B?B|3y4DNdkPtig4?{W%!j56t&H|={boWIJKt@XYXY5 zN9hH;=HLXkzVq`8a~q)IdLstUngGSgEN8mu0ql_oCzg!@yftoWm@oXDc_^7zFHC|u z7I5*asurCn;DM$~J1hzB#RunR;jP`-pl5y&j!cV&rLvtE?C6PiB7@*@%t9*2x<-=6 zx1grDA{MzNqvxwy+G-sQb?@XLw@DA$1sgcicg})N`!2>!IFP#k>vw#&aWg*r%I+OE zIe}4N2PX5~hUmY7u>YMJG)Fj~G<)xb{fp9|V8Of1e3XkLq*!x)nHuh|UCl`;yP3f<2?Y}B$s`H@zT`t@S zkD1t}=u3;fbt<-I7NgUHdKf%lOO1c?@#I`yp@+FOcvcGo7+6E@N>4CJQUUFkqx4W$ zIZ~}CNIGgrH<#W45$7!ESe1)9&BEw9xeAp}pCe11p27Py!Q`w%5>V~0(5tx#XWP_s z8-I9!wR$5B@$QFmM?YAyM~luk&!9gx7h%i|bx_snBA*JK=q2XZjhkKpA^K;Lx8oO_ znYe&@Dwb4hi2|}k4{G0DOG@f>;rF?W|8o{NMZ5WU61gvMT5llk$}Xj!)GkA0OD&Z% zSx8rzj$`S<6WG_9hELv|2ky#u*p9d1Fze*MW^;6orYkB8HKEb`*Wl<>43%$JQPqeW z+!a$2z)V}0Htn{@(Pzf^u)-Yz3~%9j*C?#eG=zKn>9py~F?v1C3*9F^p1J$Q*c`|NN-JIyMQO^a3OvMX5cS!c~LNZ;=B!u zeiu-uEx}+f)__j+&JZ}jue7mGgr0ksiPKUH@TAo{JR}@~Zy)607SSr)6!w%lYyHLJ zuYy78OfMWQO-5}abDY0J0NuLwV-EKYs{PKvBSe8FwtdC?Yw~dOh8{==Dd4F|HXtb* zN`v@o$lhp{jlFw^t~$ICzGTrL#p4S+^Lr!+uKZ*eGx+S%C|5meGAqYY^Aw!1@JS+111?)!Tpvy@RM9C=OLlmf#rpo%@etiHg%i;l!Pz&@8?T+HO!Nc|V`5?`|WZ z7KN~Xek=2UDB^fv0hp&p<8mU){DlpuvhgR0kbX$dtT2X}OMFlzrLXXDbtotX$1tW{ zF0Rjcf>L|06QrGR%p(gge-ELB+dtt+=Sn;(#yoKuudsN+5yLhMC_I2ViFquXy6)jKf#fd7HXyt3FWK{d&A=? zHvX$c<0u1o`zsn7AE&|2;%2&fZX4Ix=?8ktwxYzcHc)OGz+0!YvGDs6^vkQji(^A1 zX+b5%Ms0+JRlVfuK(}HK+sA_84;X#Qa`9SM}bK+ES|6_jlrkoTwx@rr? zc}rnP*-|jLXA3tfLr~>4W1_1(gNv~ZscLr*Fkbd*sH=-Xd3NqxUce>Sh4aaa556$9 znu~KD^r44%9NdT!!nqc^VZ{d<{INd-?!I;8Dh6){BZV8(zF-wJ*N3B9&|&)YN9&O#1K^*6tC)J_-C~U0*Sz{$2 zwYUYGTWx`wKgCa(>G=L(9Zoekfi1|K(%o}9fPohV19YI0MpJ?xHH1X zi^@|30rzCAk8eZDf1a~T7x2WDc#`KC1plNBVCOd;%G{pDcw=2$Q-viMG_``|!WI(M z4_csAv=Q$s-A4W^ZYX4sO)s@}&`EnTajRB5_L}g)s2g)c%`L>k<}x5&n24*z`IQ#D zHNa5PLR8wmLo=NPvlPyNup8Tp%x=IyL49~q`2j^uexn|zAFcJ0FnEEWQcuV?SakUc z=ly{csv3R+-`bea+R7fhq0vEY9$hCHhvHx|Eymuoe=s?p^)J=&<8_>pecB}Cu90lK;r zp{~Axw0i_{?bJ=k;%la`>}e!1PdNeFlOpJ-^(z#dDZne$W}Zun0y@b|3+r5BFzjt9 z$!ZS6TQ(wKw&M$=Bs@N9g z{XZh?A;1&13xaRM8uX4!B&a>l!q2I9p|}1uW0#-7w~t-||JP-3&^Q}f^)8}vaUGc2 zFo*D9JPK5bf=dYxK2%pi!RGbI_o9H_6OkhktOGsf-wosQL*RIM7PiP$!(_(x5Z)cm zSvs6R)jS{Luk=ik^mQ?{9RCK{?;R9E6cgd+qGH5v@u1hd8m>RkOf~*D29AFZp-`(H zY~7HEH_jbruG*(42Ugs--X%~c^cm&XNJ7!{5a6B@K&@Gt@G*rCB9`S4mlvfNx26zf zF1Wzp>5KTUi0$P{20-(%5N7`p?K^zJrb+3R_Y0Yaul>_=T|@ zm3URSf^}+SA<_C0G>2^=*8@}G`5_ya)_4Q?!_pYzrWu8QKVbj&5o?#T+!QYze%m|K zImh>6n&l6ovpo@23Ucw5@k`F~Um5sjLokf={6ax!#xIgG)cS%fIrwV~^@CSqgmE44 zpPWZu)F;8ry}qD(X(PFB&;u(~3TUCSKHQ)E2Iv3f=V@(g0I3D~Ao*?xrf#ai&Xxf> zGF6b*?&tbmzE%%4qAEe}r6m}#`Q$p>Cw9yO^zZpX%rp1wka2|Zx)r#pB?Qm;J z9s0T2<86CITyys_D$cOw)^+;hspmCxBESX$M{U8ne+j)c%Ny3sjl?I_71+PC244C^ zK%7n)EKp3P&9c>aP0R&tgxxt@1$_`NZ^ADkX~^ff5dM|Nl7+`gV1eBvxTjMAk|D3? zRpC17eqE4v@9k!gS=ff;$xK>RA_Oach;r)otFSw{Q`n{JO9F4%k&a+x)O2V=L%~Qe zEf!F^oM?xI|9J4H=rb&0-M2P7N6=kpk8Nvj;$ev@+W4CblO0w=TgwD?jmy&`It`p( z4aI0U-IOl1Mhuoa&3Ma0@cHg*?%|{DcsI}zd+*O7O(yr@v`z;%f6`?%OcO)>h0QQy z@q38l{J^X-6T%U7W1n+3 z56HWJfR8?Gp1)V2sOH(k(Ns%B`7`IhbuPivTIP6vZX@;D^n$vnwZmHz5m+Hp2VQI^ z^wBN@;zc~T*%KR4J1&ZI>YNi~b{>XPmx{@M2FF=vMT2-8;o~`{A0n-aHF$e*D%PC7 z4)ynL!l$#*;2+M;KJujy>GFmiT5JjG)j7BO2%V8(J- zyA`r9KDi84)Gxw9GfPO{paRaJ2iQC*z+6`(tr|L<2fLROVJS3-b8IyJ6m!m$24v zDW16Cikp^{(Bg=l;3{N-ai&VE-mxcy@Om&7a?d3FltnQ1f@V5i`iyIa#ntVp|~&?P0zpLoXgL|GS@gbm(7Sej^82Yf`C$4cN57r_8>u3+fjUM zlvpcYN&VeBo9$GZa5TsX_TQ-^^;e4NK(7EjRIW$j&E$xUXFnPLxe`ws|e?#@W3UTnGC(b+C%25n|LjIk4 zhhO8|=!8flbZWha&)V}aFOMHhqz0iqMh|L^J3>WS8*}&`LqWMeAaMU2G_XEmQBx8Y zdXHhKUL^Kk6a$Nr+4THo2~aON2GevcL1=G1E!h8#Z2ZdO?5fVkGhY&6@W?xO^xzES z+-t=JaeJ}G@f5vK$D?BR(#ZC=x6x8&HBr^^;>66(0Mm9`Janpp8t>D=7Q4UTuHOw^ z9eZhzxD8_-UI6cCa~wKajP_IC(Jbwg)Q;Omx7ypneDMg(5i`ME!{w;BBZV6`>lt{T z8i&3*5xVO~0MyLe=f^0fGaG_ye__(VXVCt61ruKX z0NES0_}R1%4{v--m+full#5OcsC z^&5^tv?vGcWX-Uwqz~w|%m!;AJ`n7G~udwo*yMwBk9y_Le(Hz%PNzajiCvPN~*0hL`+g*z){asJ$e@GaM$ zWFHyjJn-y;*LmxpX=x`o{bQZYh9}_b#8?v0j?;hlf{AGf2;K3;#c4d+H_d{cJnDfR zg1Q)*oeME6Ct2)_V9~=5e6lB@h5s8G*<4R4>E8|dum9k0t132sM3M7Wl_=Oa53@%7 z!FT0M6gP6g2UA%FLGl;DdX_iq{6LpjS>f=_A?~CEwj0~aftsV;AQw3YPj1hki!Xn~ z4pj&N7LOd^ay?1@b6?oA8lQxa3;8qQPyr`axrMy5qpQ=j+ zk8LGakND#D(nyj#@DY#kx#En95OQC~2_eaeRGw}DMaDE(Tk;v_MWn+Dt7u~Ai)5-$ zD@6V|MAngP7!~yaaYsd*^4~X1@*QKd?hu`2QHGDCAAqGzIk6jK@;PJ&H0Hh9ya6PzcZ|>QwXcW3qiMVh|I_g2FcN> zp!XvO21Q*l&nXpFB~FGfr&Um6VI-Z@&X~Q+GO4yrBv$;)g!=1B$wS2|lY;T;iag?jqV@(v5`FWov^}{1~8AV}rTbMPJ%UP$8NN$d>LN^66T z<%KM^J%sy2((zbQO- zYA*4`Ez#rnaB~1!pJ~QTMS4J{cj7K?D`QdQGJd%REZATS9m)Z)ceOL_>GH-yXwN*H zJd{h};@&3`pnu~&dA_+7wVMM#XFLrK?+C&<#g@o9{Rws(_+h{&VchR}0sKVQ-~)Mi z{BH9DmwD}^Zeb6JiLE5G3{Hg`e{;CaLR0Xg*;mxs{Ei+kt;DaZyP#%yCEU5)NTa5x z(JPOif#%W4p!(eqwi)Q)HyLMm_N<9=76qXJHla%X464*Mjw(}X$shfJmsF z3xUM{GVs8agJ2fH#fXJ}!NkQ192*E8oHrYqC-Pw}%k3@uz^|k$W&z64;c)zM5ND2_ zE~VxaL`FBkoX`pUD;y7xdo(!GOC@llTRy(-t-v$v=XE#TVWpQb)+_%3nH39g?%h&M z$Q`B*IbrZ$%L*Fhn9rGCQW!lVpyZ>dfsPkWKQ<2y_@&4EQPrXjyj2K{TG z0Rpqx4ytmMq8qmt`Y$X7zP1S>6j=}XOX}!yYZKxTeGPaeKOp+20lf4xgBG_Yl<@uo zzxF4>Oc_TYo7PdQ-cZ5|b|fq6R>P@%e{nSGGr1pqjfj-lVMf3JmUxze!?`B>V9Pws zTF3BQ3_B}MafaW%gIIsi8XxpBhq1^A%pBQ-mtH*sT?;QLVBd2g^Uu?pneX7h)~~R7 zLk{d+B?+M=qqwTDh%t=tuv(a&GG!gD2kl^F{Fx-lP!l!0?l9GWw?)h{@YA!wwsn&5Qb!`B0mye;sL^}<%bA|&2>D+Y^Jbaz9 z6yy9XAf+mX{+@XTS|t03oAP}QU(H2~iGIeFn`B9Uxjsa%b*b3vdIOIPu7{j$8K9E5 z5_A@4fR>0moLw`F(W+(0O|QV)rh7;ZrwJ;9)ai=ti4c497aEJS;pme;XlX1*ynlD# zeft;ig7s6s;|)?op0c_-cK<6@c(@I2TbVw zOizDTfjmodP)R5Pqh%Q|ZALF9IUuf&8H4;sHMqg+DH>>R1>KG_a6A74*!w&~rw{hb z>9Z8>@3FvW?KZfpFh+jLmT|dzY@vB0KibJQ!OgqVV558rIBKfFVINnhJKKa2D+XZ4 z03T27#wCadEr-7A?l4c@3f4|E!J(cDWbyt=n&IDp)AuG4=`BA<%2nnToY}*vjGGFj z%9Fs@Zxbo4o}g1k(!t$11z&h|(u{j=v21K7-eN2ymB1e$vd9tR6&k_gO*q8pTEV%= ze&imT8B)WqfX~=wSYfRU&PzNXE6x*UIKAKuJP3to_1VZhZ~8@sH5dW8e?8IeHL-F{<*;u_=NJ)F2Cqzxlf;W*#IN!>SNGZF*QSZA{g9`Hc zB=kV}RvCH!z6eg0++m)@eJSQIa`DqrNwUE<0@mDIN)A_4VOx9$Zl5zu;#o)QKmg+c z1oSf=*%5s1WeNhFju@f)geHXl0x_8{nA;JC;(NVue}XMqu9M(ay$k^Hrl&ARhdIK} zC*$Re6O3a~kB59R>21$-_|5PQw|)30)*2aeM1%tA5%(O-7PP_x(+yFzwheUH=kBaw zhrx?JgR1gVEdH1Rv%U>*Jy|Y6MqUD*M4x9f_b+ttNdRIgz*{?$xdqc=$^23&EOYq@ z-LqZDwWjHyJnJev6!{6Wm9ug6?Qt4vqX;^uC_FAYfC0X5Fj?6KEK8$s{Y*#tI>8ww zRhuDmnH1=?y22u(`=Eb`i;2a|6Wu4Mq>{|f+q%CI-7Nc3cZ^tJ=u;zf7#-za{~1pl zJ)eSsb~TK?UB{T+0(9Pdc`&}ka>DX-;b_Jaj7pdT0Uvj=XMH|? zbLLax?VeB1TwuEbr_Xp&%%7Ze{sA-NwP4-xV6+_S;T|#Ug)~o==lC6my*)PQQpkbK z6)JFErlh(|@tw@fY2e{ucteH{qZ1>6l*cOtvIiz#XYwm{UIu`!@cDht?D1g8MK|+7$(V zPHzYC&p}vJ#n_5v9gIbB4wlyEVX$2=)XuNM!x!H{<^C@4WZk~ip*bM!CWD6IdUUDP z((QF)aYXi@KRM&S6YXU-agW-u{rt8+=pwC43gR;HPeu{urBngev=+Xx_xAUVlDMEG z4~^$e2a}4Ar1E$diS|gMa^IK0y6h4tbW*_9$X(!OR8AW5y*U+p-{F(z9emn$2l$Lk zA@Ke&T&*8~DJr(8EiFwIXZymm62>~SdWP#Z8e;L=L`Zyj5qR5w<0$K~ja~DkTN#%_ z(k%;i_#ef+7x|Uc|JvgG0&856-vk`ZK3s9Jk!8*dQ7)+ocRWbL?bjE8!$UQ&R2~3z z)(`YOfj>bDL~r}j z3WIB~Of3gRL%)*j>y-JjR$=J!UW|%lcO{2E5}Ph(GQs?-YhoDxWrhVdg!tlnqe6UF zFGl2!9mhs$gLM;UaaM3C%ipp+@$UvK)3Bx97xi&hI?J>Qxv{++Vnf1K+UC@Xap@UY zW|;~iD$TSgI}76Le?hac2!KTp+^k8#>uYmyC`=8?Cha78{mkD`+yHdWZyd-M!-G?w z(Md8LaM3%Pxc*k=s;y!^C3ij6%XdM)$Q+=fUoq;I7<|yLrjyyMp)zcVcN~K7ZYw{p zs?wWt_^=HmU5>=KC#JaSA@e)ggac`agS(v<;gY`qZ@pL%xmzEP+*8^Rlz9Q)a<`#v z>KT{Dq%G|6oPwAE<6$ z4~NEEF!K@OP@_6(ZcYN+!p@%+N6^MTp6nKP2e)aObnCHhY-!4;UkWl&B5xj@6r7Ct zHlxseS6d*q6Vtw%}zaF zH;!peIj~k-0GCUbqTkYOoNmEKaCBi1OtVyD_i5S~l-dPL>OV8C(Hn{hf8eroJZQ7* zskG!GJo3k#`NsyKcw#?SbSRHrFj@>NT+U(Vf;Yq{`V08Fyw`bC62Gd{UCtgOhUFK__}USP7eO+oZTSQz4fu3blnJEE}eC`75^3G<-kQkL^)! z;ll>Te>>obx>r+h%OB>;X!wmBnL<3i(;KG?8iDLwJ(MlU#DKxeRP6C${QgA zwqNBS_iq-2uN{H;Vq9F2tdHN0%7J!w2UtJ2Pk)+B#Wx9py#32c;p-e5ygW4ui2>Ug z^7>J0S2_r}JY)9~P4veb9aO&OkHX{~Jh7PpI|{>4;dB#9vUkX7@o6wTs>)cGTj9-f zHv2rSLpf1|D&=9kCU6#>g$KghhaOO~=QlTPBAujF7SmS_^=Q?%5*+P+W9sl6`Y-Gz z=yc7);2W~^WXeXECDzY&-^_m@z;@_K-uTh~Es-7S#gqDJ_^#s^T=mx?%ZsLx85p~1gscu7A}P&gnB#B}PD;LqwLF&56`Ride4}8x(;6FO4IrjF6)$?c zfDO6bcnkxzKWu@w()4^7=GYfR^*g+sys%ZKSsWjo$< zC<c^XRl~g2fI=}$(#bm{7Is+8b0duVSc?sxM4UB*-ZnsRKCKt zN1d28M;0VD6{V_81fj{a=h(8U9(6)zP-%&i|97Eso=%9t_&g`tojU`zN%_L+d;ulS zw?vRJ4dh-Oc?_<*TX3bdANN4!LR!Or9VHhS;K!wVU{R46>bU-;X~L_>4;>G@ORwRb zQwN~EHHI5vIRxL>-ZA{BE?tvXj^?wYiH_-fZrGL<%xO=giSgECxx6T*8rjl_vPX3I z4`b61LolPuan^!H+!{WwI7_Qg`x>A{FqiF`^&sMX} z0H4yDFK)2mXeOuitQJIVtVN~DGF-X*KYV`l2l3t&i1hr^<)0W8ff}B9l}+*K-cIb4jwCm@acin;czVkhFigfsk*2;O#$5a zn(*-8Fi@u>n0~eeHVPWRk0)V_m7oSy2MNZwj1kU>cT{>|3#qnMBHb&WvQFYW^zKNZ z$6UFntkO;@xA5@{+t}{savl`=JVB3#aYXaxCmhcHLt>hAV54vurX`Kzf$RIZ+PzjV z{eUsyZRg@p^aoUXln4j1#<49y7k4xEnU+{M9&&G?wx?K^_s|sFR6hnr`>HXc%mtTK zuY%wQnUEJZf<3}+kY2D11J~Pg1 zAy6l>1$nCjxp)3Y(Ruh&{rz#=Xi!n9RN8xqrnu*QQ`$r7+tg4hEe(~D$jq+D9!d60 zvfcB(LP$21O_7nk_xhdRAK<}*>+?D9^M1Xa&jrhIX;~I(v?*d_<0q);m4;0_WufEF zN|^hOxznOHB1dKn_u>Q^#S6jA{~|#@r2^)kn@h$UbZDdAOOn6uIV?3Wf^IK2Og3!f zH1#Qh)a!8!ktn1g%s2E~E)R>$_ba^XD1>Lx`)G&6B^tTU6C-sl;=Ch9H0sb_(hWQm zyLl3wa+i=h$KAn4BoV&d{6SwnG{Ko>%wzYl9#?BSLz{#ZhHh}g;a7KUka6BLfm_1Ql#}#D95&=7mTbU;gO22= zfdGiRnKKu*HNMPsz1Y_mTL@`F_dQ(7W9~D&)(r=94TWm~@j2MuKag2vC9t0jqa}$m)iKKU%m?v*U z1JzQ@i1foDfYG}cztIu2b6nxd+}k8)f-`ni`$KzV2&G*qC>G;FR_QLrA)``GqJA*B zwD}F()L~4x>3y)ga)>-K_QE)B2ibZd1q7RGNY=BQgd0;^VC}RZTx)B95l4pM^}!~* z^51Nb{Y;=)H@Gn4Fx0I_=$LhjJba zg!$vgbv|Gw`U|$L<)B3-<9sidL6K@*B6R03@mt5k$~7i%M&tSkAz^bgD*Oog#W z-yw~%ez@6U>=m^DFRdxC{qKGZK3GOF?7o1@hfj2FvJP>84gKL}`MQJ=xaMg$LK< zVn&fO3T3)8mR~IEd#z*qxj7ILdW>F3xCswmx&!WFjLUILG+;f|Eu1{~Bm9}V-l;TJ0KjS~CJ?s-86qJ7ApXlLvU zyo}06brLRSJK*A<+Gzc+o-9w4ghu%Rh(I5fw|a^{oc;f}|#F_BO)a(LcE7;cNQJJr(oW|Dfu#eE8BoPR+)o$e5lT ziXN`PcufP$z3hfHJELK>|9$$&l1Nr{IhM)ZW!|G2@>;F{5(+3>yb1JP zeH|)%`pNEl)zDMG05ZpPiC|$VUR?Q?p32uJkI!wSGr$< zH(_v3Qh@V`RvbfqCV7w(1c{ptQ>{QhsQZ2y!iGvvXjKVb^pk{%4|h-j{#n>&!MaJW za`5cjUKE-XNt@@k(~5E#@ckx90?tpscb}Jo@pCWM@6V=cjV17BnE89A-at-cB0e1F z65s2$IPTU)5Z{r9E3SL8U7Z?4vVD_K$N;|Ec?38Q*coiqO)z?>1z)d}pm$UPPLt}R zw}$vIBqhk7w?32_xts&4+6K}$`?0xt2Wqk`;K}*ZvE&iO%pV~n#GnK&WV39?kz^85 znTo3yjT6t7*$E%ivY1=*9>ziiRNB6P@lobyIGg}#CZY7d#eu*J>jAf&QaJH6^I!07 zAgr75ib@_($q*iF+VmL@r53}q&V8`7!k96VgHSQ<9}MpvhG5^fbVB}A)cw~Flh3UK z(Uc^Jn3aHE|J#8}Zm}-woOR&d!@={DKI4)l8>sbm=1gxCAoo^QaIXD%4H;j&L1`xA zjZVD`Pc0qbnQk*V*76Tr9<-sy-F#R$t(^6m6p#i=VEVWs?)>IQ-`W&GK;Aoeddvru zw%B7pxbOwqjFT|wKF6^x8=6SzKg`B5=n8RGrq$+ z-$t^k`zMS|bzp9Y&tP7hfEV8k!qo_Sl6D>-v*bCPsM}3V2alj^e=O+|LEJGY0+FRY zL{v`)lBG?c)2JOzMwd{-lL@5s)n2%}ZzJd$O(*-e7}2a1tUrA1C$ycp0|RHeajNEH zUZRZMMiD~Z6TN4Zu-ibCob=Ph2eWu& zontodm)CFDm+elLY7Ec|te@}U!@Rb&QTTN)>lnUB=X^-vkP0z?h#yWk&}@g>HK)Pp zspBwfRTm0}&H|Yit`M?qug%zTH;OmsRu%p9xgD?22n@V#h&v3v zqD$IxSn~J?xPHmN#>qh#IJ+Na4>TpjSxN9Vo$|ooSTmGQ4+2$G2d*fObjwvE&8-8= zL~A^;u#C1R3xeX@N~F`{@yG9Ydg#Cccqbr@Y8pH6aYYp-$NZokKCkdyx*eS=H3uvT zCc!+Tw-~fXm3LxkA^rQq9qu*XAq^{n;Hy^v9CT`=F&q`@n=lc(y`RA0t5=EEy>y}m z5wJ8;0het5iW75wW6;l7oc-R4Sbh(s_75H4h3Qeec1H=PExd^zBKq)oel4_E48tG! zH>hn|iB^}s^M0#4QGX-AGB(R>kM-xhttp0~k8g1GDnafEnGaZPrvj@PUqxk6D|35g zU?P0Pxh?iM$H)$TzI=r2C{^ z;aJH49S+mML!Fi=vrrRyiRm?%0Gi`b#l?Dqwkh z0CE1%jwK=W*n2dZ@iA86>j~LVJ6{9}EKJ}*t^!To?$23N*Gpf|z6)H>dc0twh8K3- zBLk+0(^C+p$w1V#^8(3UG1rLRdkt??P(6-|n zURTd$=c{4dIl-K4KXnaEG+e+Y+6Xp$s0F@SIQ*EN3qkin@af~LkZ~sp^~A2j0?$++ z{|WPdzhU0*5X9Iy><;DlOSFwEV)>eOv>JE~IaTqP$NA22w8{ff*1y>6B*<+eMKI*6 z407E%u*lgI9hHT-`}YhgXfiHw&}<8I+jJMa&bfm9dB!WXYKKJK5t!Q|j}PnY>00kl zkUVi4BAv@%us0I?Z}XvCZ!)E)6VU(TOK479Nh9{ABViE}!QWiZw5D(}l}Z#@5fF6;H5MXVgfh6!KrGVeWdbq2svvKxxU zT7y6^nUu`4anVpW(7qjq4vNy-)U;%iB z_+xtI9NsR*S;?u$hglwG@M+~Z9_i1gMxO_v%-@*$J`v`3WM#t6+5gC*m@Uc@bR(P$?ij)^7T%Pb5RXz%{o!is2-`=d zfrUmMWZmj#eH35bi(NLP^Is}`X8#@cFZF_5uUf!z;vR_oYlQzi_@riAGjGFjc{r(; z0eb_p$)1@muwP}IRDZk-BcJo|@61@NzZ=QUNSQcUG?rtygq=wimceLZ8g2Vxj27Db5!JZhcrpFOQNtyZwxH9+*Vrc$Ou4T_V9wReI5BB6I<*Wy*5Q{h zg*ZYs>*0T~sUjyLJOFDnagm!nt~ugNzOy{+-}mEJriM1 z>v@!4=}Ucu%)ycE(lK=wxG>Iw@2MO}(OC^Mf==MGJ#RR&yW}uYzzkAUlyS?W71+RX z#~z>07W!!JVu2dgvnb}B8Zq&f@?mu9mEzJM+{wLa=bBnijD1;|DMOY*y zfpU%&5Nlpfdva&P&AF4I?TsI}#yaEKc46*br9WU(APEcZ3B%v-$FS8(3MLtzCW5|? zAZoyfHmBu7h?*(AZE1jyr`yA8=GSuEnFVW+`C>f1>8Jr3wYUSWN_4aNzaHd#j6lAi z7UG1{V3iP(+0)m+yHtH#xG@diFOnn9^B1Dooc};e=>qwha~O71Mv^MNE+(WXp`B9_ z`K)0EVRn*uM%e*J?#3b2R)UJE47_-5ggC^;!sZ#lU_G~jWy|bf*IGSHj6MgKW*mf3 zmHz-mE#g4c7WTv^lYWPG_L(0=#c&I>Z}q`r-bM8PZpWW9=Yv&sJo&mZnCR}<3JV_} zg~(=hrz}$d5*JpWY(okxn)elD9wrjQyii!I7KZW4uTl0>5y#~~H_IS@gjJ_ZSO#h{ zM7|9r0j52mXU%#!`mq>(_y|Ui#X_h@D5-@I)E91nWlbY&zH3G~zA5_dQHCkYw0Rs6 zYwS8=O0@kv;a+Yu*xB)sEAtZev7aN5uZRD-oM38XB}Nv8pcnH$yCfFF5>X#`@iY-W zt6M?hx*$9_7J^?*vq36?a-PmHNjQuLsPDHAaB)BeJ?90W_=7C8oT-Phmdh}D_!%lX zTu`Bxg%$jgcg9F;4Z z;detbhJTy^Q*7*Uvi&ub8jr*2&8>L5M<277+hUC1R}ikYgo^SkRKFKbQvRrc`srE> zsK_RZXa9!_F0a6)bB*ysUpvbO*GcqcH(^VAX@EF3D&Xia8|kps#h^yj_Ex5HtNd%9Tr%^cF)(#^l%yX zAidjs2?w6N#xZ?g*u1+4_OiZe{A+j0Jio+yLM_&91sKyE!_jS498{LeB`5|v^lXatFI1p8j2UQ$Fs?8lCUW|;4XOTY+ zjS${jqOf7*AY`eH(RvkOC_E>OOD5})NaYyJeDMo@Pxb;{IP=fd3vug(`*8fmOWIo? zizm;2gQVT3ah6ppN)HucS#cGvJ>mk?lusj*#9@tG7OM0M@ONx($Na}pSY)#RUAuEJ zywVkIt9a=2hCO!`XqU zk5=rA@$cSB;(K%>c`_seCCfBX>tr9etDQsch95Y5cm;%OsRQPknmb{)jtY6|-VSSyU55ULjrb$w1xScZ!W)kUz{}RBYf;21&`cYA@%0)ayL)hTl5f~r3}MS(ROG)wgpeUiw5yY zM&v-O0NUm>fY!5KJe)jA%j`{QiCG^#(2z&pM&#iE#^#*xZ9f{FyNDA+T4CoyLns~n z1zHPA=#LGzaaznr`g=(uY&a5ycLT#==ExNK{zwaYxKVPv=q?VQdyduH`q4!(5q#bj zl3<5$tk}GXh^UM**V`LhxrsTG%Cqsb?O|2-00=VuM;5z>&@y&zU#0tZ$INL( zuq}Ksh^g1X3O7F-Y%hT}?QO8VC=oNO&tvWqe{hbO4V-Twu%q9F+$rmYLst@zr(TNF zB5E<{Wi$jA0roE9aQ>VRgV6o?upoX1ZfR~ne%o$Na`0GJ|0?x%P$FV z7kdSvb?6NUdc^XpsYRT9%2g0_3SoS)Icbl0j|t~nFyL(+IXs?=rFk#mh>b9R562qU zIkLUA+zj&M*9^$Juf$nl){o<3h46{(W&X?hMS~Rl>DDxBj=V@XFVu2~jI0QTdX57EP%bRQtLLWylROl|v68s1;Sw=LiJPI97o1kEe z2F&vmMgQfA@bW<{KJDzriy8Iwlx-HMEKKIb_%OFjGIKi>=hNHs{OF%`{=AW#94t{t zp*cK&><`VPwGsdB4_&X zzVJ%OboRq3Zb{hTC(Svu<`vcXc@j$pgtr8@eFuHwZl*q`i9Mu<^SVZCz;wQdh%4 zT44^JKBYn<4k)wt?h{x#GmU&E!SHiYDK=FGqB6$>!sq>>N*}KBEDycrXoy$BDQ_oy zH=~x=*jPb|LkW@O4WpCfA85~zBf@QqG02MDoyuGQtEyEX(dbD;@+`>@J8irbD9E3{ zX4LJweZb&A3H%iF;{2Huj6V$mcq3B>Nn^kxP-_{4)LwO*B2a+uxm#d|RVvPPtbvJ! zHjs9D60zioWXs%?t zJ`QYlc@CTJAA&z&gP8lt1E)TcB+ui5&@X&5dAajG`L^*Pw0`PD%{3OVvn3XE%H(nJ z7e2ZD$b`lnEQPDvg!vm4u93{f9;%aYA1h_Vp>4reGFKF z^v{Cyt|4$TXO1K@Q?zof$CC~7;Kq4ts$We1o$`HQyJ`{Hd@y~^SAOdF5k9Y_SB)cwBU1hLnzIsaT7psL^| zn0KqA-I*Y`Pcvbqp&;`RU&Hmk7O;1UF?Pp&MBD2FxR~u_{Q`u!AG%d=o}C5Fp0kZ? zI`I^xovl%-oXaVBu?0X>4h@@Tfx-D^>{WG4XzS=B9*vLCdSx%<1?fU;bO9~ePw`VZYN;$0RKS19xPUibqRr)7%A`#eIOrD3g;JltD(24f~ z!5x3Wc;i}nclI+3);GuNZ;d%AUS8OuK{Yz~IHkcxiVI>^pssK4%>u zK}HDl)lb2E&2c>3upde{FOom#<_zy%rZCUC1?{}B6V%U{!YV^y{@maHz|$g^_$T%f zE!Qn%{C+#UG2Rut zoxi~b?@p-eosGqR72!XrYFHyRKy24}QB}!7=6CUe9veSsYn3j$pG>6rBAk$p31@+@#@2bnwe|IChWulX|{l5y=C$q#vAC`vx@ZaEJRf+=}-vC~_0~9gN)sN-EWZEWgcqsK7 z%Op$4$}1u0anX-%`BwrP;>O_UtTedeeGIm2JO%=@Qem$jy9bUo=R7cNg`kzcILTqQ z)N~)a&_Dkczuk1g*$q2k%(Df$SFA+qu47>7K=JI@1zyhWZV1axDw*_uGmXBF7HE^YR8Qz{J%wK=V4PLKz!rg6CISb@^w!`Tma9JIRD=~>@wlo&1+M3O!VQBSWO$usyfEyhB-bdPg(S(u-H|h6n!Km`uk=SX)(pgOz=-YgmDu$jR>W8Y}>FPAN z)aVagm9o?#m`jec{oiQh2Y4Z!hVd4wp{({2P2O`Gl}i(FL&8Vcm+A|Fo9^Sc!PTgz zl|Zy)T4`a^`GK&4xr@ z`2-#-Ik3%Kn7hs_AGp3rxH>e8&0z89o7T-_C3)1hvz3PY_{Ta)Y!;r@LFLOrDLnGR zgaB{YrP=@n_uk>aoMAkEzYPxl^?}6)BnfHs#2sC?!CGP*erv6O>xn_&dwl_so6d(b zAG`5;fhB6*8pFlAj)P8sB?kuz(P*Y8HnpYVb3HQ{0tk6pkOlCUXa97konh?!7~V9(chblRadq&u7SywZO+ASD-F2 z3@+KF;KE7yaP37s<5DTJym&Q=DMhjQX#)9u!Ug{;Du4-Hnou*h{Qo&2s4W+UM~^o` z;@_{NU<)9}Y(CFaXH&w_x1v;QMFT2tYhoM@1vpXE$}&`phxx;etU5x$dt)Jm271iZoqQ3#7?y=|hl5X&xvJhr8 zyaX4+6Oc2Yj;D{9V%dWQctv~;HnUFFw5avyI;sJawLjqshgiH+C<;PqTA1`j2d0@Z z|89v3b$Q%GU&yq;^n?Hw68(gp4qjC8ffM!_&xX6l>Zn$}9c+p&!>42+CQ3{I?M5Z) z^2ZtDR@_`0hg$__(XX97 z)b+?Kp3cwvI6cM+mhdfZ_kRr`*p1Q*qi|E&Krs6h%by;ABWOeCh*i|2(QN!K-9k<5J+Ef zzFx2)|7C>2bml}`&fXI~8lOqd-$*j8VIgD&_`n810jzlP7bc8`D3LT3qpk_Z})=$>E(@X-X(pWeZ@sLV6 z#NqAvot)!)xiH0VF&^Gxf`LnW=-tmsL^|dhif8=;lS%uCIqTWIS)>l>r(=ltJOQq0 zx+T78Xi~@u%|MS5wsTYe54|{R;c1QvYCpY;!8|uum==o~lWg$t1#xJp?7|yKDcF15 z3H)T2!;6|p3eWaj#^<|Q(6~vIDEw=}4VS|)wDJ~X0mtIpU5rQPbPl>Vs-nw$BMfSl zz>w5_&}bFlt||Y8ZC+iF-6X^n+(|KbNSdePP>}PRli-_9?fRHw)Ak|ER1oGS-pV8r7iK_%vkw%_KMso7 zgFMqEUm;4&7j+oduzKzdY~0{a_THRKy`5)K8TAWLW;aF$x-6h@#{evNC56HKT70-a z0CtNdvK*5HIQp1k^zQxSUT8Gxshq-8S0$XayOfAuw*c+=EhzF^8sF)8gJSqZ2;MBn zZH(FjTh3|$wisdG8f9?1+=g@eWuc&gaRjGa#rlq5d|<$EqZ78X&e$B>>}iSVmwzOL z8(x6?kvwpJr;PedV{jtD6~wn!z=w=~v`S_cR{l4id9m4f{#F~<847cQXFEV<|5=pN z`Hm7wMtIQIfSh{ESk_Wvc&Nvk$m2Y!BFq=<*P7vY?&TJ)D&Sc{DGx>DQuaDrx zX4naR&&k2DTDr0*3tdgOqEf+Iyw&N(`W3ZsD@F-$e>X3QyAY0wIfL8uD2}>I3>=Ga zp>B__)AybM)Zi$^c`veT;LD@9{AxC? z+ol70M{{uemKV&6aOZVi{fTGy&jCr7RJ7R_NV!k!Ks7yvMr0qwX=a5GF6$Uyl#p8MXU_a?EEPZGN2lbz!x3LkNvuEy^;R;wBw*{7tw1XMT z&;~v30`EEN6<$h);}>=p8S^cW_Ahk9Syh&}U{W*)oNNK5=Zo=3^%VFj@EW}19AUTb zVcxy|1;pfw3sn`{M}(C^(EfoC=U3=DYK2y?^;9>ibPYlRX`(HqW0+rY4t6~~L-j_} zc~w^^t{X1Eg!pJw3vnXL&x&7U{%0v=z@8GM}Aa4n$SX#o6|JTq?O8 zS0&wmOY5h?a^?X_>^_bM)U#3G^+>{kf(XL1%!J>PMx5>D=@8d*7w4RQgMauscyo^l z1hKP)f}0bBR&(*(ZXcX!n2x+8FH|_{#)iqmaC;7g`*}$)uOu9$`hv0iCS%X0w37cU z14)VEESRRh4P_3$=6!M)q4%}#F!ui!Tsq>1EADn+L;6zYZZMc__qAepV$P4j!TuxJ zuz_`)vH~GbWd>c_?vHBKfw0-Uh;)WW!-IZdt}f$UOV{yf%YGHec36oy6O7}HD#szG z$O!+)HNv!dS9mdJr1@$Qdc+$=rw}uOH|J+%Iwi8dlw+=(#j(x_X#*suqqX-vW ztw+s&&j9j@q2;wKzIkj0_tzTYu`K3)PP2r?G4)tB>IibO8F2A(Bcwm#(Gcsa=)Nrq zM^;~j$#2KlIcYX2E%d~nx1I3;JO%Tk)hON`gN?V#N!4>*kglksizAiTOg)Y&S2M_w z6CY8e*#z%h@*--(0^E!l!B}xj3{v(JaJx~2iqF{ZPi`1IpV&gjx$7j|PXocG0k+3W zQk^r~;m{L%d}we2xA=Bpm$f@pD|y(NRm)0e=Z_I0q+hVdCnMtPEYzrf3O z9jTrb4jE+yIBVi14Ea|BRn#9%m=Lt7I<0kGR7sohR)9{ zgC4hnt}bhZ0p46XrZ7 zstDKH&B%N`A?_n-84Su|Zr%k?a6>>P?2T@O;Psav{YxI)TJBD6r5zy!+fTxQrd%4j zIv*A{@Q}Z4BiLBkq6^DRZCpD9>sYtpTYE3ORK5)dSNJQ&4*K&Ut!JIdN^Ra5*o&5qP>6|&0Hf5 z>Wm$Dv09VdcdUY&ex`tH4{?sp`wADj(%`O{J-*lKq`%eeQNws<@PA) zkfC@`*&mf<)9}Ghw%?J{qr!SGaBhqutVo$fUu_lSYXmf~Xm~6R+P())%^ft`c?#P9 zdrze`hiSls1kS_3K-{sX5$0&@LVL$tcu3aBSDyMo?P`sc zPN5h*HxP2;cF|Ne6DDiwQN1u9lHqa~s)~7VM}7{N4Ub{YjSBp#qKG270$8^_2UH9M zxw5C~V3X=L=;MTd%F4{&cV&%#{BCKG#t zGB?_2#A+8}cT0%BW!ZBo|JViJ%7ybDt?2?qp+a;iQiJxSI%wMEh=Y>GBr8)EuZ1LH zmSh_m+P?#yYy#YVW<``D%Rthjlzzx@rzJ|Qc>Z|}^JTcfYUwOA>@9_U%|l@Lu?}lT zQ=o+1U6tONifTRn%rnlij@P~6QC}5Io>C8XasK2;VGC>$HYQOS5or3}24^RqC*px- zP_L#-CB}WoLw*U=>21ZGmrr7~{UGePBZ(K%>v+bL56659VcG7p@C1H22=Ya)rQtlEM#u{l;0mAfMyVjy!&YsghucOmb@p0ZE#*OG9q+*O zv{w4-Ept|TPazS!g><;`19h}=hQ+@%@v+}KDl)wec3%EXj3zFko&pEq{U=Iv4Gdvg z}1EnI!E11IXlpKjV(rneP(EVcrvHdsfcwO%BhO+Q`o+(1b-`+V&1b7 zD*a>tY}Zs$pBu$Ig)3s1s?h+K4y?vRUner%^ zR>P&4uFMY^1ZO^fg+UcQM9*-BMXCxAC|Ce3&%Qx*j3C#`wGNEtAA%%JVZIIX-W5M! z_mw$=a7eI-S8w%_F@2N3k(Y;hwK@3XQyaK`e~Ud;c__=grN(95c7~_TAL$D+E4aNwl zpu5ummFr!NPge37BaCHfb)R5EOD*;m_@N&C3NDOkA)<8}_ch5-rSE;%^pQ^|me;|@ z=suPadWX|}#uGLrd4qUw3m)C(iJrzLSa2CW=S+5t214ls=HK9C>b*v28yF4ZaFO_?PS&K6UF0sQr6BT;m z=uhPTVQyu$2T&Z@4OuRR@b$6}*`U@#msx$GPmDF;)`J~rs8NcKHcR2V`@(#$HggQP zwTPI0w!@9|EbHKnj~{2Hul7Xbe!*%)!f zHGX+hF3X17p{95rR9NfM^yDy%^YbTu+HH)r>W`O}9tQEST~KBi1lNs%p#S$6sOo(p zZpEYp zD@U1=b)7Kx)u5Cc{-9%%h5{O|$udF4OwT!tr~6}Yn&K|lc{LuAf?IL=sgK~P zaD_NU>p()0AYV4YjdfxSV9WY4uzeo~v*+%{yG7GcC2;`E*Vw|*wnZ4ZC<=7zN3m-l zlN>XKOef7eW=D%VWMy zAI><>NU#s|@oSGcK3#GN#cIUy{n7+{G?YjNST^?$M^zzqq!_=&UBrb0LU3+U0y=vZ z;r16iY}q3LO2g)8TM!J|KM?wqEugAb7YkH~Or)DLb z-XM!%-vUTNdk=;h%fOr~rqF%+5?!BE0B*C(ao*K?s1(L}xANI^yT(MYIhllJHCepM zWiL7Bw;rc97aDOojpIDku!Z0CqBzhIfdQ}7Fywe02;MQm1=D|1*K{QuI28$%piOT0 zdNStbFeK(`;p;Dp(RxNIT|2EG`~S>C>v^AWmk7%vZny@)nmw4ir39q!1)#fp5B;i= z2A>;pI3Cl*VML=HUN(wAQFIK72)w~^I}xb4Jce>F)N`*RsWsf=Jptl<*WwnY8Q6TQ$xFmF1G5G!dOH+$Njt^JvGxiewwNc>+?8*rlbos z*k=hN>qT(|I>M{{y%_#^oR^VTfYLWYVP5?LP)P5C%460zM_d%8i$v)KuSpzo(Gy%Z z_K-#Sy`WVa1f8pgKv|{}q%!=$(mVqVw^rkq^LL@PcnM5RzX-lv@9?g6F*^6%f+`1l zTpuaS^;F)9?N;WfsACAPW-US5G6&)$g6Q|P;gI{lgBl3$gwv1Sz&z&JeOIsw_AIQz z_d!o^RbL^PxrjihO)vzj%s^8`wpVT24pPdx@Xr1kGSyZ#E8?j(+4PPgz`Y%^x7 z`~i*ou_$`t3mtYHC40^=mSS@ZK&dDk?->B;o-BItyb(Qc|1}Og{sSYsJ$Y%0QMg_F z7JM>1fwNCJfa$&@c=$((c$Ia5(8La`lnO$6>joxCTR_(?ZH%dwh1_f*{!Fb@n6Q~; zR^%s9{ZM^av@afNkV0h;WdJF}U zt2>g2ThK$8WUfhc_d4T#K4bsA35BEsn&8XM0Tz2@@$&H$EcsOlstuXOz5LAZglGr@xqOk=g{)jiOb(+vCn$OB&eqw>vFmSv z!F`G!NKG{5aDESuI{&H-GRxNGiZuw z%QN6ac+!s9Rs&=-aUbtuX9pfREzIrpDa0l3_hY12HEc4;!#h{z!JAFt(8-$xPapcDvF9+X ze>ea>_WmgT(~M%%Q8b?$K@Pt+LG5`wxVb6_ii9?Su)$Y4SW^cQhOfcRD;^KcxepI+ z3W8CT8%mz-z@pP^N7<~6VZQMoJ>v>zi&8f7<_6e`uL)dnEIaE9L!-~Z_(7oz2c#bXt zixd$Ee{2F{jw`WB;0V};zvtz8O(Nq{wNQViBX;QvVrt6^D2@*Gf{)J*s3`~cnWYcchSD2%-x0ORY9xN~ zpB)%8pYKiHW$Zdr0aZg5ct=W?ju)`ojEGmT>30E4?yl$6e0fJ{Ofi0Ku!Tpp|9Fo& zg%q48{=}aq4)`qLFI>IBx*ANE{88dD7_8|g3L1X&(uo|bjuhj$YL~;6u?z4pu^9%B z>cXIU0I`(H1?wrfxH!}a?<=z2`>A@=Ig~=w*2#gWv^1pKcjKEW_H?G(ddw*JKr0Wq z0|(n++sq;S>$;hiB(0XViwV8brEe^lL--&9d zc}SSM=}$QnRC}Pa?0Kppb`K=w`f%n_=4ANoPeC{Z_GtTK=_b}ueRG(;j&y@f4f$v; z+6cMVq)}oh4fBJd@%|qXs`@Y;x=&Z*)_>+W!ZO^#u0}9wFrCg?IEvM4TsZ$Z=c3!* zNjPuDAZ9=J#0kakA(kUd99CFDQN$R!ZS}yE%ayS2(09&6@juvc=mq2cn3B-xS+way z5AMF63Ey5R!r-_&hFkRF=LZomZJIXz{^d+=ePsMG$1BV$$r$F2?3|fyMr^8#@s2_< zbyGfu!Ty)1{}OrVukV4BV;krU)kg~LW}XD6Od= z8xzYEO8kT&A>IQVuDPL>#d*y6`;rEv-GN=7!>~Hd4_E)b0RK&jf`VzYpd6#X(7GG6 zrq<9CJHBxi<$2+g)EJnrGC~?I{>1}-_d;At02HezfuM~WZDVeo(eV+qxEzB;pV~>7 z(L9g{j>gVtXP7hlA5TE|H+eiS3KOE9a|$fhlP4xsP${(#ksh$ ziO#_;Ur(65=^_rh#G}`-kMQb;1-+N}7^lzc!ZGiD+@j5LFN~9UK4ulP);u5z^>bk$ zM-DIU*$!$uO>ji(5crok6Tieybn|6)_OJ?vcD*;a@2e}0y>g}-T7|e<&s}29@ISax zt{i51cF}Nw3b?Skg`MqNaA&X?l$CiwllvZQF1k$0t^Yz!hylF(5spVP_rTt37je?s zsW@9+92aU!(yH5toT=Za?qt?U+mZrZ`EPLPBqcb0{~PHL6h=)CA?~tM@hI0P#Md*J zi6T$ev-`Usx_a47v=1ExKh~p(AL3Ajr<+mrO$ThvkHJvSKj^r21Vx`*$GMBtz^aF3 zr6Pp+M%8<8%*9WBPPj2yKQ4)BI>mVL4(rof8KLus#pv;@j*cl5(d^AL$?$L(UKK0D zcZV_{Bw`Kk%xnYnTk}7P&O4my_l@ILl6F$Gr5&lHIM03Bi=wSm+NG?@7wsaOl4Q$X zl@UUm=N2L|viF`Dk(tc=p5MP*m+Nw_bI#{^?)&|Iy>!u0+ZL`0IzejSUgQ@Y0U7rr zusrS=RbQMA*(>J|-I{RPB>5M29pa$$*X5v7;l*ioPy?RiFnmqvz+*xp>^}DxEu(*d z*@<~zE#FLH8eY)QUs8C%;SJks`(n(vCVjuO6NfFV@$G+8Y0LN1xN@pDNN7ob&h{th z(Ke3$uLQYgui4=z8#eb>NP}sAg+cRZ7R(tBLtowVpn2;rhRr*O{&oHYU+$%?j8k-G zTN(7Z*fH->0H-}70~O_t;_C3lIC1L#&xY4HtLHqvG|D8&bEIg{tNA#8>lUb5;Rsjw z)alXHg>Z>K0&m#4A}?ME0*-blmnzS)#5=58{Dkw0rU6x;G$zG zlymzl4SV$+89@)vtaiYQjBmK1@c|gSO(D~j5hcSN;h^MO^8CYh8m0FGKj>D2Sd~1) zd-~!wojkHJ(+20s34o^^h2syBQ9o}6{yo>obIenNdSyQdU-bbz`|hIEfHo}G`2+9% zFebg*A$as_6=R`fpp(}GoZHw=!)!OhYX8@$ky}L6&IZBGwkYOT+mFkb+dy_jAj_$I zC*O|6(jOsWWJ!e>^|HGU2^MDHHr*WMi=*J`MR!ok3x?zt7kY0`I|+O8j&tKCb5snS zBW)LMqM!mvJUc0Z1Kaq-7szw zfIHOFG5DSjWOi7Q@m2X$hVf2&+RM>X+8%cv%ccYW8mX%9XN-z?1ozi}L;banV1D3V zaMD={o4*|v&XfR5wze5BndHAYkJx;6e0*k&E*mu7X_7~V; z>vBt_Ytw)85*$rYptY1aUae74X$Mbqbs%g$;sD>+uAqO-Ej%o?1Io1wXk5A)skR8h zDIqISl(FjTwB8ajvK5Tpia@IA63+Lc516792ZLWb$(p8Y`1!?`C@I>4=j$RGk#`Ez zQ-bk~nh}c2dPCtCzQnD|uENQso)Ew{0!Kx=(LO2+&c|tj%KRL<`;rMPN-M&?>QkW2 zX@+XOc$%!qX4y@xw1GX#gdWep)@DikU!`eDX@EAY?qBq)91%8C6O z18caM5Ys!(k&JHuuj&HE=ez>vXV-&t*iX!knnfJiv%zYIJje!3!8+@Y#B3(Tg)$=$ zv~w?(l*U4d&;Y$zvJ2g=1mlD1Rq$T5gt=lA$x+t|8ZGEetdqo1a8n9)h;72Yd3g!{ zTvt#FVaDfs8GyY@Hsi15ji_ta0!CLF(LQq&Z*d)XQzaeAR^>_(y)X|iuzcaix?r+T zW+AvwW!=`uEOhwcNkl{#zc);hHos{=;nst6sxptB-TZ+X@9V?cvZu&NqxYcDz7+K$ zYTb}rV0tmS?nxL};zaANr|l&4iP>M%C12z7tdz>)r7 zxKX_Zxu&l%{zVXa_Z=exM$UNu%o5ltB!#^L0Wg2pEJ$b1>$|UW@ufqj(kk;A;APp5 zNz<-?IOB!i7<|clbMY;eoQQ^w=LJxx@P@g^#lcy35%OJC#G0{AD7(s+nDFEW^PK)8 z-2p~;V$wX8*T|tk$I37wZXvk@^I_smEWQ3)m@%jLx%w3=U^~A9X4Ms9MI&FLL-8E= z9K8tU_ZBgpWCic6TmapDJs2JsurtE?e$+3CB>md%_#%jT<(Ug7VXhe*+*C&1I)8<0 zF3M==&$?hPEc3lR6?XV8Kr?>k)*`HHU4IkvoosOBbbDA7Q4devjNy|RKZ#;#CEfd> z0blEy;;tZb*zjx#xh6gfvN-KvsceU7G1u`#nkZcQ>x{Qc%t+kl1-SR66z7bHKNfe- zMc)7c?(ec?xJ+~_z3Qn={g#vw^PV3la#b52PSt`pWf{=A-;}(uD8ez1gV^tD0}K7@ zLBTl}Pv=Y1OFMM%#GG01@K_UZ{x(j|4MlNIZ;;?v3so~t#t)PeQ^${X(Rg-tGmjk7 z2CFl|&>kcUXS&_!pw1uMBKV0X?dnU+?U{S+^GSGjbCiCQWUkSQ%h-HoJ@4Y~C!lRy zMkb#MN5>f*)TQkT@=nCSo2q5(f?S3xPekDI<;(*-Z6^F~(gne+H}D}h3KvZefXh=7 zamyr2%>QGHl~T_YhhKQYKY3SNG^-i*CtGrqKgB_L&k&KgeH$LS_JZ-=-=Jiy&oer6 z8N@elLzgi2w+;GW-`VHH(IXn8Sj_P;N$vSk09|I6llSK7h_P&=AC#o#!)fd zfzI4&c4r&Lh?rsgV)y}%HCBL8#v#}`OOX3aL>lINwL+nv-DrEt1AaO9!_W2CP+n3V z<(7Ph|8DbfY3x!qr}zPm{5&+S7)0rZHLP3u61U&TqyHVRgmuGDv08N;UG$vEnTfsF z$@Zk_$zHITE67bS`HPV|K9SYcFHqzpW7dRD!(IJeY;Gg1H22OgNWJ|Jtx}y(IoS}M zjhF{z+Ix~vF&!rDSO;>te2GV-Jb2mslksp*FY&M#gEMD-W7?nf=1iL7}tMo!)ehoxodsBY6hj4wGs zmh=_avSU3Sa@_})>XMP%k%2L<99%Nv4NTGXhu+P#kXJn!OHK=;$U|?aOb|yIwS30w zu%X}HmnYbE3J^Kkc|BW_{brV7q-(Il=eixGOiKU>IdRN_jFjsVY3ZkAE??} z4Lx$cpd4X==j03Umz^fQa|>q9Q$fspxd5N2xf4@KH$1d=2roJOgE=w28^*vz|hum=u)d5sA#HsB#& zZ`dv23@4rWNp*?^nj8oQS?g)A_Vy_}Sf~cK%k*jai6$JCi6F)e%J}5%Iuzgi0$Z$? z!~T~%e7_?b%`#?UqhLQ&>}Kq?L_L`O$rZMp}E+LrKOhXcO9C?R*9rkRl*g#hd z-JRluLcV8G*>DhpAf;?zj7{a?tYDzIL z?eXvf52&_YjKg!b@zRWZF?q2EY@dII{L1lz5Zx-8+x7+KZ#WF!9&dw@$O$B>8?mk7 z1TV1R4(hIbfns&1I40~lBVNS3XTh4Vd+jhjYiIsZgLIIc6M)C9@4%h1pR{3h$|Lr^Fa&brHyWxfO)!75 zCp?ty;e_9w2_x?xl3~dgcy&!7DJiVPT+b`?P#}L|#-E$$X($T1LZPr_egvFheD%$_ zvmoN)Q3zJjU}w;`n3rLNe0yq%=iw;0_B9H8--N>T+36U1(-%jRQsCs(VyszS1yxU6 zl;-Vxg#UHCLT+mxoLOl`w?F!YZ@;_Z(?{#UfVp@xF7y+d@2L=YUz9g=&y)UlY(6P< zk4L@TY_|3;ikRAFH02tg(naGj?_-6cq&` zZ@dVed))y}bR2Zs&V^}u*(f`(m&{LjhL2K?;{<(9I%hP(dGSBAyYww6<@`sB7ENa7 zxe>5Yd4kivt3mbLN;2s3l4#{CGiFU8el=FcgvlO2pZvnL-CS6-U;v`@ZE@}~SBOo$ zj-Ryh!RK2P=f1}X2+U}}wcjN0pm_w*|7}TAR!Y#;LxoU(-4RUObU-WQI$rr=1J)~y z=+M3!RBm1)(MtA5jjlr|%lnPe>4o6BE*i%!<5_?1$~5??5|KAaNIa*34shsQJ}wE^cZD$L^OGIKR20}wa>Wp*<(nDC&Abb*X8s48b*JE- zZC=>>>I2ZYHsIg%0p_o*=Ul;^_*9tX6Bp8i;5w+8a0gi-aT?ZZfO|LYgrj*WP}dhH?YStMLzDS0!dU1?1hgPRSEyq9Gb_q0ANg3JbMx}Wy|r;13qrU{%mM_&AgJwA~EbB>%DCi1>4-`V6`!r zm`^<6#f1COIqQ6}LXG7MP0BE-hGiBV&5`HvU9qG-9$19~Uru^YT%^0uxo9S8ZO}li zAPIP#mP)*Ch!cCWa!ymuW-NZ(Ns+$5uU+Hlv+O-+cxMqIwb7O^{!*pZFSIg&qBxxWhh`#=M$`BMYKIj)Smv-D4PRDTnL* z4Mc%Cv~OvCrP~I#6W_Cc=$hkud1S6BnUk%JjW-z^|H*q?()|(i)4VYLlP3-{CX1k0 zDgLV~!ATPWi328kQN{EwZmM*JPRn614(i44Hl6T&RRWy$i$iTTmw9a_3c)>{_;-&S zV)`njw59h^D>j%&Dc6X%E~drG~=4@`xmx^%~v10t*+Xz}S>( zu!s}G+AqIQZA(6WFiM7{pN``K_W5}Iw+sAOc5iy{Mmm^j1y$<&+@3^J*roXmU2f&U zZygWpkkNtsgIeUr$QY`}R1rvAs9RX-<$9Z9kA*gT_?D$WP8s=1BlyNbr3o<^2iY*8&It*t^Pmt~} z?ws-}A+&txh#EsGXs~e;Ufvl;r*8U1<*i@fqd;lQiPJ>2qQg);xg2(rR=oV7j_z@o z!s|cqmI$}A^K!EfJe?~=SG#8s6KKH8O|Iy&={SCoD27W;Upc3T4`bwBN0hL;3GRH`V4ju)mDXM`bF~O+dJVwsQ~$`~4d2o0ARkxVoW5E-hlvIUOG4Z&^&F>D#T!)L?*4iKj=6R-AFc)N*S>{S>H>)w z(%(^dods$RWU+l1``-cwV6WDH#D@C~4jdEY8kq6$?U*;pM)J|chZ@ky)fD!m?!=L2 z_OSbf2bO#iB{B+LDAqDctHVlpF*TQIZgMds|Ea;}*F;l@Z?Y2xTyhZTaw|>$Qj&w>oc6ySj=%2||2JDj3&(;fxE^^M!={7{0ubmZjH&{F-n`xjlyXPKnnnkOJR> z!ijFldESz&yLi?>2QoI^B}XI6;nB2(xG<4r$3@nlOvx4yUZRHCyJL|X6@~Sh{d8y~ zp7dUNMYWT%@Iy)(ZZG`=HXm4*XN42^aYi`S?GEHpMhwxayFtY_t_S|m4B$9^0GF4F zc<=i?JeA;v9#M?J%JS5&O2)~)4_$akCKJ}3i2ym5`zV<)#wn1oBC#t!gY24i)J@I- z)mcx;gB|@ag&qcjTsPEOF35eXqysr=lOgnp0|t+uhJ%;J;hS{~dYc+^23_8P@cMJC zA6y5{dy~ORun_jK?t;&q0k9YwgeNR>skC7`6j}{&k{6Z|bzIQwWjs5W)Rf zEK68DhrJHlF-6@P>P}wciF!IvxZ-XuZrPp&+uLf0 zgU1m1<1yu%oXme?Zm{rrf}zZ5Jy{;kN9P|;8M#3*v33TerqII=cEvO-i2}e zj2FPdRVD14w2lZ*t)@j{>!~p7irJD|D1F<2+R3#*qe>slH91Q(=@^O|k20R&5J=aH z;Ur0f(j&W2@VNt?kN=66;t~AQ2GJ^^mztkH4HX|;AUN{?t~ky1*nfB7QO5|d&lZ5h zKN*~k=pvqP%tN}qm35Ww-@=<;S??=j1Vd~RsD7s-B&_^M`Yhr>^jRK!l+VV1{Q}%^ z#Sqq;8b?tT*4^K1ip_k?$uQLx<;CJjjDr_-b{J6V_^XEN3e!o-Ls7W!eLMJs{Gx@I zEAg;?CvK3jfvTJ;m^Aw>ZEn3lg$;yZEUX3UmN>x8{!zSQm<&pj&%&@w2ffl+j4ppC zP{_}Z=ew4VJ1;#QjifEbZMmF4-~tk2|2N$xIeTABiy*u zY@ic$4ek)M`VYz*vasXN6V!OuO;4EnppU8`a5UaQM2ZQx->S#^f_*4&rG-1!`Sa2Z zv$0nPK(9;$KQ~t34UY_3x{J*?ubRNa!{O+)HIQ*Hrb0sJWX4lz2YrQ|IP3Q~YzgI( zHtApFjl3;*x%k4SZ_;3CdW7OT@HCw!3I2hT8Cy__ z%|7-#|# z3%NI)c&Dd3!&;WBWVdu$^@xkNCzUb+volz>2GRD0VrcJZLzBVD9FLY8RR3QQ6u7Ry zjed+LwaFceZz}S_cE5$kdJcH9qyoMh1#-v%HxSj2VXo1?FtoUd%}ZyZ^W%K#*U~~o zID(j!lMUf>eRz+r2-DzHZ8kG)fH}fRQ0=0M4`sDbLnRXz?%4`XCIp)7e?m-|I$ls0 zC5FMlpfk$D>x_%~x7HW_3!RVS;-4T@;S;X-r=pb7QbH!Ht%H+KM=_zu8u{;c!1R4v zDF2?5uz1g2?B8aA?Mtd~YL_fdjynX?WiGJJ_HUlw(yRFCIDg`obanDM#1TG)-XNZ; zAzpLA~)@OjlRN3iiF1W3~z^R*7KN;vV>;upj*; z$+@<%ow;&?z_fJ&$2<{2&V0hVKlXrYZ!fqF<$>TC12}S}1P>MmLqN%0YM<@NcFv_} z+UQ5GvF}kcOCcQ2Jb{IOcOqZC59Be&-Q5k5ya2Z`tmMANan&c#uNMY7$5mm=+#{&e zX$M9*i=klgEu5k;4NegLM8^kwiPKBg;j}JYY}la**X~APMt?Nr#*ac%k23Cm5f8FY z+hEG9Z_v_`j+N`;656jb=id2))LZKzbVOEwrb{V!Sw}HO5Oc%mxk1bIYPu#x5k<1RLM+-%JoaB`Y?V5(faX<5KX4v8on-41x`tu7l9=`FQRA9XOWkfLd%nGAG0X8WUe5D1Lx{dwoFOZx=j& z|Bs44$--KX0?azeGQWI-82U&E9{I|U2VWlHA4R@Ia(grxa%(}O)y7F z$rK`lCP8N^yALNOaeU*vh+L5) z?s;+^5@y^aM&)0yqs|)dZ7U{&%A2uiqYFeH6~w=x6SUP|9Y5I0y9&W|>;|X6cU?s}F+?vF%6PB$l&ISg7q|D*fz_!E_UoMCBnCkA{~ zLievy7&@Ry1=v1s{(Wb-?K>TO%5v#ByN{5dd4RsU^$G(lw4ic88+GGvgJL&d;+fPS z;=f1;f39DL<$0gc&O8|v(%7!A?E@wraHA&-kAX(A7xSF1AnH1qu<_$s*r4AHUQ)uC zytEzV_GaSnowpoAr@xqQy%#klt4+z17JT?I(C9zPz zO~K=%XQBV4B~%HXV0{K1yvTeIEqeCoHXzJ+!TgD_o7_R4?TZ$$Ih}l&2K;>xPx1@8 za2=aZN9%P#%~elaX7!OX*i#8Q?Tt7G#prA6My#pxBr0iUAgTHpp6+>pwFw_UF6<}W zc+wsQi=35qI727I*zW@#B;SBy>mPb(q#V8^3SKx z_4*~8soM_=*vu|kwHxLseMc6a%SSHL%NlE`;SDL_wbv zIFiq!8z=GOrSqBe$`uK`)p>!pWx5XjjW~+9I~0O7^U=Su9pXl>g23?~FlyCCNX&2W zPw2*WkDJgqHwQgWZ@~tkOzLuJAC|1Ff*^||(tLR`F1~jjRx{6Hn}!#vm)lZ($F-=Y z`wSM}Yeb`hBp?qq!!Ls$xb1!pJ}SM!D=B-4rek&B<}1Uz1nn4;`yCe9d(!>ShZSve zeQ@|>J`~ut(ihwg=9FZPX4_0E6ZRH0a^B-tSxx+WI+q6gC<7C#Qaqa*Ob43s;tj6H zgI?4tu>5LAW@WqpHKmhyz=zE!Bqm^o%3d~uFehUVym4mq5%MLDJ!7|?;e1{+3iIU{ z4<@Mty4*OlYtLtvf%pb#N6XNn_7kp}Y^amJTPzFr7vgouhY_8Vbg69vY|7qBC;iNTq^@PSLSYczpF{lSI|VZwMZo&c3&=U_ zk`N`xKEZua=-I(?nc5$4VfsIsR&trWpKGBwoiFj3y%HWYdkHf=R(#I9b_|ccdk=CO zuHfRUI|%sQ+b{ZP)?Qmeo+GH%d0-q=RB;3r4K?2R+~N zP+V~Ku?ikGpNboN4ufkp>og_^a#dCH;|HIY z5YMtKGG1titrj_GJ$@Grj-P{tuhzo1e%5cZA7l(wbC3-a!i0HM5R%PUE)$KcjfVsIgpEct1PhUWwlb1w7Y^XZ2X7>jC4RV#?O#-P(j3mBcF zga=|B$jxbtb#VF~3ithi1sp#VZs+H&d6s}A^BZ_>K8FY7HBci_lbHGr6800uD`zvO zM#QYlS?Eq?lAsn1Y<#^5FWpH6&)!l50RgVYukXz37lr?A5J(L3XosjrX;gS#HBM_h zi+B8gL;vCd2nx(a?XoGDe{KxcM(`*0Z_B}xr20ALETCZGfK)tO*)6pyw@uGn}31 z{PAXL*6Fd`LS25Aw~(+SlIQY4e;MoD z%Cmi0*l#o}`bM?4wV|+n40Z>}lgEvc5GCxE?YsBhDKQj^Bw+|kVmDLokBmA zRx~&lNRKLX4ewY%^=WlB^Did0j+-=a7UXW zEV`S7_eKcTu^x^v|9hxVXFbNzUnnv98jG^`8$<5Lu-)#asU*t#9bWe15bsODWP6AVh8arH6>R^t$X1LFeHO%z|HQCPCKy*f zs)FGdKL}ko1?TVmjg}jSz{1WImf9AB>EtS2h9Bd+PIH6B0~xqd8y{GiC(6;$30KzQy}A~z9%l0^|j zHF+BJ-k`YM=?xUR?1e)rwj4-*1t#lc;HL8gimxlhAM9KurzHq}^EO~*+6($pO@ijs z%mmvAL2l|5GZ-(LpnUqb7OCNw*DIu=nCVLq9QG>U} zm!ilHYjADtMW<{(Y%Y;T?Omp1$M8+`CtlFJg`b7iU<(8%t$0%N)mhT{&bGd!3E=LRg>a6`q(Pz}-80Cu!%( zGp={{av6MykJ#^w3nt)nd@0JWxsBDSvUGE|C(LMShpl;j;4?>xGZ1IR_Sc?d z8JFF`>i6JOC5{C)-ymV} zR~Ve>i#tmiaDw&9_{B!x*|pU)YPb%##x~G2w#4fjZ$}{;Z9BHHCu_@I`kfG0}F! zS!1PCu2z})gp}g!ir47!tR0jr3~@Zx6Ue`pu=8>zibe<|zVz)uK{B0mQXB&YPyMu@c?xwkiOgRT*B=F>nNU-_!3G?*o@GeGh9?9`Y%eHOsdubs? zbqL|K{6d(Y`Wg?srO?CJOHy9~81tr_%su2pSFt-{R;VgQ-rfn~cWR*H*=lI;GzInC z7LbYki%&FF>0s0aFt7|joOKwgXd1QJ#-C^!J%V?poCeQbOA{^zbdfX*Wq4WD05jIN z!`D+>+^k2yS|K0L8}egc%RYE=z8u4E|HT@usd!c>1?C2(;nWLf(Zb;^&bxM$yib&Y zc|H~x{_`IeNaYgQRguv4N)2WW%)^DjOF;CA2DT+Hz=t^_^xu~v9GCxvqZ!U9Y|5V~ zR&PxecYNds9VjF|*MfP=wlQ~0%}*ecQla5x5U9C~!14D^bhyo&aoIf3ys#e3q7vfY zbcf=u&~jSl(}8v|6X4ZAz}M6cm4s&Fld(@|eL@U0=y6oNz8VK4cVT~GAlZNR7pC7} zuVv2{&fl<0H zVe#7lIO6z>(`_3MUI~sM^(Kz=pB@3t*hX4g#n|K4CQ9F@P{{jY2D^T}LfO=1z-6xI zT-R{i`XCd#9~xtl=PRO>$>zFqfF3k+<>~HXIRKU`q-*ujRbvte{;CHlWdf@G{M;i# zb3mbH8$6Gef#~vHyf!+9H>2dSW?3jW^s+2-(n8p?W)57dm!;Z@o*=PQA3|*}qO=Z$ zgHg|ULz_b(sPrmqyk81?UM+)1c7oi9X&o?&XO7;}OK{fkVmLFd01|z5B%Y^&&Z#AE zS?mUEn6?;$^G)%}rhPb^CqYC0-6Z;xZ{h~g6KuEp4#Oor;QQQe@GP)I^Gl2ySF#^J z3KZcH0SD}<`UVe(n^S^oWn^mG+0;^Du{Q z2XFGp(uvJ={Xns)5|*z{Ba4K~@yCl^2-cEBX|-fhw4sIE)zL?r_I^0ceoK@l4h~SWjl`T>=Nvi@<1|J_wfPDH+&tv9*a{G8Lkc z`OOfm%I@{Q%MqVM;b!KCxt$#cP0N2n#pNHcz|I-dlxE|kSsU@cqY>1(ycAvBPJv4O z6(!CV*4zD^0F#YE0M)bUKi{o5UepGAvTs41gE@}z?*!g*QPLoD7#m$npr-N@^mcy$ zqCXpgt>ST*IXT8=G(nxjD+u}clI(pO0>kH_AJZSg{YNb*7#q*dZ&z^HtMK<`4?L2d1Vf+1fRAPL)1Fg& zuqqdf_cInib0CdfDZovgoC5~STJYTI%^)i42*=JR!2Mru@zo(uGBP;=nmQ}+fpjc> z+~0IPNSa$dOkH%A@%jAl^>aRMkaQ(gXXOr2Vb`|caza*wUNQ|Cv(XMp+R=Xv4X*Ii)Y zX+<{(8Nj#4?}$*?DSBq{D7b_K;Lo$xxKAUVj$;ZgmoO#!_}{<|dm9u{_dsPK#(U{> z<$T{6O)g&FLE^;)6C=N{9GglV9@sULj0c^Di?aLaW6=w!&^HGkO_hUN)$Z_U?HDX@ zao`-E&&AFkg4{{dV(^4_5HXSu#(6{T@VO=s``j4+M!ph~ZijI$cNgJqZ%e`*k%9gs z3yj?<4)y6zK;ya(TCX(1Tf2WyC$Ukg6%@>T?!h>wT?)zmDY(Ts493>J#n)dLV>}Om zKkz$-Icvk!tIr`+TZ-2pBTH=e*x=55SDd$U6Nz*5p>0a4$gP(kR(X5TYR`Stt!Hi< zfpXZMeix^#3?f%pcBuAx17@9#h0%id@UQPBI0=kmxXB+{zc>t!l&_;Bce6=8W9J55 zm<}Ql*`Up`PbCL_&`J5Tu(Y8Go4z^WydO50SQ7}99`A5t@UDb|OpS2nRX4;prJ%n& zbA?>HgsY3QXwuQwWN7p^^;8doSC*bM4nLyG>M(k*_d9OAWdcWv-_X}#E3iErz+ti; z6waK+3;z{~tp{`Ax>X%?eMp1Q;>UQ&*%D%9_Cw-_4|L9#Rj`)Z1C4cK^yGsqobM&b zeV%j;#8WCD<&7x>_X~3S)ZDOjLJx9xtJCG>e2J^ZVnN7u3P!srLu;ZU>^NEv%2V9Y z^hYn5``#YtPPBX8`=Y7V!F~x51(J-jL4b);g|}>8kaTpdexh27aqC%2QD( zC2<)}H*&>F#_{<0`vK#+EyM)5+u+v4_DjWnU_gyOR=sEW5fCjXfNSzD}tbI%iZ99@COml=??QhSNM zU18(R&wa|vog>737*q&L=XlYD z{@JK!(hULYy5V7r4e^|J7FWMnK?+?5$-Ol;Xw+wjF$W^xQpg2N9`)q)uo+8+cR$DB zsW318Mg-m(>5O0LdX=$TTtV#Gb9^Wzkm%-933m=xV@XjG$^@CvOXmd=drsYfn#=Xr zd8ikpd&M~lnk@ItxYhg48Sz#JY^HakUX!e8L!jSx8Ur*I;nRhtIKwHB=H^6#+J!Jw zwJYa6Dpa8R_J4!`n;J};v6pBRA7DEh9<{si9{)LLqfeI?Vee_W)}Qh!C&^)vzb%}& z6AIB$4&XMI;=Yw`RB6h7yy{zkouNalzt2WP%=?6VDvJckzP18A@c2a`tw= zqyvma;G|eaqWRwffACj0JJf~;LiMo4PMc@onhAqq%t`pYSLw#I`7o`Z8mEij$HZ03 zAXuRUuj%(Pw?_+Vo2{nvw+Y}*;jPq8H6O>cY!dpkN`Y_3AbRrMLhEa<*giH5TKXTu znoDMkdtr+s^22B$vJ$v^+Nl!XFut75@@pej&}Qia^FLEqUhfO<7LIdnr8(i_H9yei zt^}S=mV{Wz9Gv4?179qn@uT7pr{Y=%u6669hpWFpTjfj=BHajme;&{kE(2ip>$V?mZ@ z3}n+D^bQ<>lPu3tt}+kQdSdbT$_G44`Cjs1_dZ;`Bmfjnm(jIplW-(C4;E`xL%w!-_*maM`IC`}p6YYr{K`s*A@+pHmRJ zZ4oG`T%(rTL%^5Kyf-p;;`SF#MBy!|B-W?dC0HDPNNT>q|*+$e`xw*3$Yc8fc!Nq zv*0-iv-bAFOqLD4C)5nnwpx+snZ2Y^mB%T%S&VC=9>I3cG(60?=KdvQ@C8Pwiy=2s5M-AafLCfaYvy~(r^M-_pE@A+CdzbH#W?n zo)1ks#_*Z&OL)lUc-dM3@Gj^Zl zh5YBti?+fK^qt)46rEvC*YWAN;bRMNGR}t!CaGkluP|(vYrw(+U-UX`O4k;AW}Uud z>^R}UeCs2awLOiq^u$gayYGQ}8y4cykArk;;1<}`!}gfnByExk0p)p&Ul!bq zQp=xU=?y_{_H-}u_TeZV->=7O_CA{6+VC2@!o$In|1z#le+o-Z_wfGP90#=61ssnH zfV*8N^tM%z!Onx^`_^jo?0G_8R&}A_nN?sDZUJ@My1>6V05_Rgf#}6FSSGy&;vWU_ zNSzLD;2FBEQY1Q|IuG#@xac-vWbbnrO@kED=8Ym4Ye zuq%uURnu=-EE8H)iIPDupJ>UXq)vMUgg-~@q7PxhRNUk$D~`U2(yNT6f4A zzXBe+cEQ(LXSkKngh!trhC6-#5w-k$5;X4`?LDEJ>v2kbun#XINSXN>@xV?us_*3>%})3IZAdMc_YPOdCU16M3y1 z+N!*t&Wd17;Nz0$A+843502pFZsyYE)nd0)Hc@-oMkN>i!Lr$!L@tJ6=oKN(Q0Nd@ z6XK3miy}c}(E>a&xEv;q_rvQgK~S;yI#$W$(%69@4EYFzxQ%j-ogSuJ1DJzOik*Sv z55rogTo4ho#l+9ayoKApW9;~{gb=Y4Xe#s&4AmY(j!`=AMNlj@?>-8j4NdV$MhNJC zDT8bC3ZWq540OoY;H&7B(6KEB4)Ybj#L;}bJ>w?+W;0nmcOTRXehMlIHjtYg0d2G# zCbMVHKengxk7oCjkzCyGGXq71f8bQRT-@;R9cG1^!{Dt%$kM-w4_>MxtV+R2haPYo zKS#mXlEdKiie)>N4$v%FQ(%Q5)X+<&9(IjN`64bjIbRf?zx#ywJ4f-6?O%9%I9X8i9da$U0jF~ekIzqn0+AjP!|#Sl^aPAex`EyU>+w$L zYdYf%;j}5X;i7Ki|50?_VKu*R9B)cS#urh9tdNyao##HXS5~A@NLF?fvfG7*N=bvJ z_D9t-dB+zF%<3YtT7ujO zk7uERNdPWMUPYu!65-y&<=A%48T2#DK<;BCR!&^dG+jRDXs;y^l7?oBf~Jqz*^+C&N4!NgPjhVNBcgcyD7B z8dtp}o<$GP@TMVTRXL!-OmU(yGZfF9@aFBR+KRUfT=7ga`)sY52vL?MkPzXdz@B3oq{tTFZEE&_cJS7i8tl9kk1%x)_fJwF|U98GS z8@mi@n;Zc)k6se7Z{;AWuL#mdwoz-R<#=^bI+ihRM3jabEX@$WCTfdzP3KVTB=gyr z&%@Nwd2o=;pT6Jg2c=AQ2Tc{^YR9|dp6`j|*>jfvoaT%!s*%JnP8)Z4hTuer5&B5L ziv8tSlC&cLPFA>+ilYL2rHa*9dVew*t)B^=Dp8!xV^5%LSuUPe)}UvGTcLB(I4-d8 zBPZ7GBJ;OCRFZc0L)|;mu)D(&ZWq1c2yfd-xa1Gy9v#G~rY}K7{X8B!-Hg2&_3$e= z3I*j`LDn!ERGs^9t3)^b@h}`hvcA9#eMOwyHVtlz*kfLK6;9Y$#nZUYc9Ki#IcZ;$ zVbR(;D*U@1Y%Xh{+jR-J^Y9X8uUCKsrF`eaz zo4hCMI~AjP871-$~gv~oo# zZf(4W$C3s3wpT{sKuJHAwCzSYvj`?&+yib~%^`kNhe&eSoulbA=Z1^`V*e0W6mF%; z+#^&ttrL0eOJHwa6!D6YSS|z~PDC=~nj(POcWpGjm{bh!6t;j0Ck$_E&ZGs@6-8f{;WcYxNZT{S`#nJzY%au-#^;R7aL|-T zJXjuCupEA{Ou@3fiYTId5Dq*x!R{$9>08!sw7>Tm59oY@hDS}H_;!FuDoj9uTbJ0b zio)zIj4Np>hRqR?bf9}2OL~+!_ln~nvku|D!)JPK#xFGdWr5M6tFIu0Ed z;!j)u5j28}ais;pkGqz^vgxnUX7hH`(r)D4`eq3(S`+c#Ny*qKFs9E7k_{%y=|O-3I9O2r5)N%nPJM)c*OBuG{12Mtp4jK9c3Y~Zl)8I z)nw4`OTBodd3~7bK7q~AQ+fGqqgdmq0&0Kbp;`SSsP<_?*I_$6^tBLb3+$nFZ5q|| z9fXF0N{G-7Li_bA(KvrU=jdryw7BjJK4h!w%4UZbchc`9aAw zMCEdMG@2%gch9K66$=f_nP-RR2CE@-n04qZN+5Dc531ehz*TDbc+_wy=Brs^>~#;2 z8myy+ymP$5eL-+A(izrWodct*6X1PC25K#HCKea1A^m0x*%%^05(H<_Oz~TsgNY*e zA^$TjnK6z>wB3|Hm>6U6XganYqgd;67G@~2d19(KI%+MU8@AObPijyneJuabc%~FW zj}*ccDK9)z<%o5wH-UfmAg=%U0NSVf(2(Ts=w}m&;-4~L!y#|xfZ@XwO)1oLs-sy> zZy}-ZG8)NeL34r^olqIVnW2cxU+zHQ-P~FZYEkt#IN=5Bv&B>Cq;hiK(*qwrum=5Af6?n9aE5MKz?_AMxzi@$ z=U&!nId_6rS>nUnc1;WA4|Twm;8WQ7y%@C0Tw&~70InQ$Rdu)f?Gz9UTjJIj;Mxv@7!sxqk^a$w!7pR3<665grW*jC_Z?M)I zAyy7zu%zid$4X&{>gT1B@YZes&pnj$A{h3~r@Zw-t|+<2jKjSV%+9BxP}PzLCDL{@ zEJg;rF8{(NFh#Q+@z7S!+yig@;N43feCl3>WR$(@mU-jZTVhz>ri2F9jWEkD2_{+H z=Z){~z|YSN@x^yv`l$C9nBVMyGdxP4#AlH+tHj{`pdV;I(jhTvd@`#(5voi!Q{4zI zJX*0F&Njv2ucwniqs)}l^u9z{GENt&55k=YdwBNoAB2@534XjEu%!@E-bT{MCQHyZ zzl*MuHxiw_yP$jSO?uQU7!0N)k)-XGka}zwGME0uo7e3?j&;I=&1|5+x`58T`Hv^F zSrlr`yPrW=qd$+@hHHx-9AS3qtU51Qx4&=_M2 zc($jGe0tS_Q>ITu>lf=_-h^AAvqTuj8i3-&T{4+6YqeK>^z*p>%*7=Ck+1c8Ip45 zB5?`8Oy-MT_C^?^n|9)25&>{P8AY>VN$JZlsJ^%yLME1Bx%@t8Jy%4e4i)2!^@Whc zI{W%+2hcZ)&B*FmKRH;CKikV1OWv#E>q#**WtiP57uv$|g~oVo`9icQ6T-y>+rh_p z4yX#hLAmHG7`NX|Pe(n2ZT0`Cx|ShoN-5*1AX#{IKY^;;6X3r%Cq*R(s>$U*Tewr& z4g!8v_+{M}kfZs$6~*yb`t2`z+h!BLjf~$G@52+Z_QUfdc@VzW7c}Osq~>YAQNZCb z*%4}lb@zfW*X$#iddQiGG$nJU?A=I2PB6yGHznStvyM14PYy31Na6JA#Nw8j0gzDq z318mGL#;k5ykzkgRQG71q!8oR=4PPN3T^nt>3}oOqj1VOcbs}a2+8Y49Ps#rE?J)N ze;&r_Wg^@|4|jslE|w)pn1?ErI#ipZk3Q?(aTI2jLe%aUUXEw2@{~0T!CNZ|7iZLC zTe3NQ>i&^4!*DgiwohnzvlCZe5I`^*B&*vRps>3U)MJe3l#VKz>+=^|?n;2LflGo$ zLl7ig)WGT-Efm=+PZPerg2J=GAg}Wpcdsc!yI-LsHGB#_`j`w-k0SBlj@_`-CxYI0 zSWoM;3-D8f11c(AqEE+HQUT)+uz%<#*gXj$R%Av{1l@M z%y6To9a@N4V5XwGQk<;?D0Yp|-ow#kS3@pcK2i-T-LKhv=QG&m*yA=mCwl(HCvbkn zdhv7P@jsg`(xJ>);lJ|nQm8w;+{5k*cTUmux$o)W1z|ASm=3+P03D=K$m%VWXeK|x zr!NEX&~7_;_$-b2Mjc2>?RR`*;)A)`O&GUg81{V9W;w(Ho>p}Mo|Ie3D@&1qQAZ=> zy!{B<^y4s;&Ol6KJ}2!C_-Ee7aX#0`(JM=&3Ul6I)u|O=lA{YAGM4y}8+# zO%-0W#%VJiObaFgV?x*+=!q)JFJSfoL#WMcCSyCckl8j~cz?YcN_S@B%lu6+e4>YN@SsHM~O_N$3HscK4PUoP5KU_!@;D+ay{^W2cOBj?JcBPs2Z3m|!K>~B zXqs~dPF0`5=JV5_Z*%~*oOwldHb$U`&macmxa0Pu5y%$5L*LBd>Y1%hiNKMuW74^AtLDFF~q(3*>z^ArgnJai*Fr^MN}+z^!W58H|Q8##Wmu z8UoFlwy>#Ch(Bl*MISUMqN!gOsb>!6eCbO1aL)*uC$OF7QXy{Sw0g#F{tJJ0KZWDA zj@a{TfZi#dg3GtK67wT@F!ufrx>jAr`Axzv3fWb zH0gD^x6+J;)i{7eZ4o$LA4VBACzh@~fn}#>L8Mv~?Y!X58ycR1T{a(ZY<@kFS`?0r zzotM==xP|5>c=T-y#-0d74T;57IbCLwZrO66z^+c-oFM~`D-DaH8=y>YTPl#w-5fk ze*r#g|KfsDH*_pr0==>ez-UbhMklp17JvcWy5a*oB1O24&HgT?W<%d&mTS>B<;1QT zqakKpn75a`SGnD=pGJY6n=&SDGeu+nWR$i~ptI*X5yi8EXm)WfEVVrf23u{=N5+TK za0M}a0b`0gN#gVJ%hQd!w>-C0a|6zfH)Gz%U^pNk0dk>#Q98Alu@An` z|CWy6F7F$7o+dz7#bQvX^+!k?AQ3CsZn3l*$hH(xJ+1>Q%aQZsN(*>)oWWyxRU{=@ zgWaP>@btSJVmnj!R>Wc-Y5Csf`j!^r!ds5AZsUuntV zhCv4$+0zRh3u>wC=Pde1#-3WP^@dh4Z<5s8MIMW=nd%1%<#y9I)Ffdd9{fI)WxT?% z--&g$I1_N;E(M&`vIS+9O~dj3rh(H##-!b&gsp*=oOHuLlHqB_GLwE-^S%fwEUsew z)OW|$a9vRU~PR{6W7KaLN#cW^f0PgEQ9&kY7o3n7h?rx;q3ns&~n*H zOn4fD9y3}XjS~m{qLU!vhXoWl{$@U$TriBVhVOgD8RuIMXKt>bpZvr@w|WnF&5*_G z?UCTJAry|u>*LiKyWn!|T#%6dgm=SaKyXto{>v8Nn~UCoia)tjX&Z2tof zAsSTjF2Nzq&z!-sR;cZl!OMfk0Dk4rcZ`pu+%!PH3BHFEi5hTyehk(gcu4z>wKIQZ zEhI`=!WjuiT4tn%tE_IpNL4@fNEN{FBtuBdctce(iqY0QlIS#Pf^fd$vn+rJ%x)r^ScT|bz=P!*z%>VV$MCQQpsqh3GrU|IZ8e4i44dPhAV&Tk+Xb2a{0%;RF5PEV3Zu|4${a_iDRcV2b>^)L<_Z3v1wjl7l2Rl7j zKdyZOsVSez%RBB#?){brt86oPu~-=Q>D%F$peuE=yaKO|rK4UR+w=Lg(#X^#s2VD}vNuD4aX#`qr06!*|J?TOJl4N3!NAK&ya$RG z(C%;@to$_*qS@!^Wq1p1TjPonf{le?3RX>n%|_+;@x zmgTGFOZalq%ifUW%$H=6jx}y_t%F~}2O-5ffX-}LL$6N|;`WFN@Hs`M@cgkn**A9t zc^5qK&82iKoK_9{3;Qt5U_Sb@Io<5h%lJ({A71H|GM{t{w5EP0a~!NtY}Al0^ZWqq zF{%mr?*rhozXy5^d60?z!u;6LFCfrmiGvA)I58m=;uR00j;tR{&53~2i}NVa5azCX z9SGwwn&6Zut~{(R42$3?@mQ3HY<5diqy)HrR^epd%_L}g-VIya%y6yjE8=iLh(35H zgfjo4;lt8!EHEhNI3pKWL4H*1fnpDGRm?iD6^04C**#)8U&ss1tjJ zo?l>y^0W8Rk3JWOZiEc}{&p6JPErtU(!j~3N{I>ZioGq}&!XQ&rVmaS)(;{GFNfKRP{1k70 zn}dU=;&|SBD2xa;LLC1KzFsZ|u0~(5e@7hlr?ldUMtdqV_Y6oZy$IOwA01y9jrWx+ zc;ei@cz%&T7`R4&Q|c*nyrV*{E3-S4jU{<#&|(4=ul0TmQEsCl5zB~N&)W9&;w)B31o}Id2n))0AqNK1CJ6h zE#U@wEwRPTy*)J8J0Fity8)hz6O$;disSA_aO14Yv?e5lqtJ2_Q_&Rl1_k(rm9DV+ zzuRPRVI1)041>|mO8lcR1$7xWGC&}NTnVm*7aJFm`M1MK=f@j3{+I{eDYIc-NjS@# zvEDhG0|hVlhJO8eIPgiB*vB4$a|>J;gG87+I4=gLPO>EG1xr!Pt(%M<{!UdI?!(K= zQUD=gMEAuY#B8FN8efPlp|@{$(ehBHxZn);Y8)MwO8XuIYu>~!vfnD1VoHuDku zK0O^XA68-EPFYUY=66uJvm7LvC|0{4fXNezAx`Bpc@tNPh8cS~F^mC!VLD^rABv&- zvzyU#q667%#R0WDZXoaC%{d(YfiZK1`PXkvhv}RvFmLm7wi{O^Uk(++#AkI78hVnb zS?5v3T`~B1S0>!x)RCV>G8~2b+Mw{@HY~lP3~z3jqp#XG_@}mi2QQZ9 zgF<2ynHa2x`FcYrC3y+l98~bs;Xb@vosJsKdw4zX$8e3FBM7&)K!OAxmTCUSa*685 z+i-)-Nd8IOWv1c`x07I86@sfi+Tq>cFJR(W1j+w65SX9>?&Ecst(uFX^QVw!=YG*( z{wEl97Ut)rx-*wsGq&x{#1i`qc$)tNr9{4C&!H6jYj_h6O|ymd>k~=U{S}NgBMl?h z1-V+|iy3z%7Zf6yuU533vv+eTh@~yW#GnuGebOh`b-NM;ueO5QOve@3i$O^FA>B+fQD-U3c~<-b7nyO;b-KkIrjdAjwl|V` zHb+egArZ?Yd7=Bq*=(yHDlU1^jEFJvp=~C}?^}yCmS5odGIPi;+>D_wJ>a}TEbcHe zqqbdJp&}{<#95bq`)X_Wc_NbS8J$tGZ~<(;F%eFmY=p{91(0HH1goQ*QE9s)+-k@p z#$SqX)R#HMUTfjZgw>#YA_5kE=}4SV8U$YqQpo-0QT#8c_y6x$Xu6jNdPR?sY+Vad zZ^z-`#C=fdJpq1NB=i0(&cd5qHLBqiPhXsz!k#}Ll5P_K>aR=aEnX=0eM`dGnK3kW zG8awc0eW^nN1auS1M2b@^)>DBnKlt@pHPsIVIG<#$H3)sJ&?PB(EMu{PuOVT zZR2R%eN7V1&+^5Pcr#dC_7bl7mSVzjZ@e>04vz3G;9Xi7w&neWrRp2VtJnmZY}v`O zI!P#?)(`XIRuMz~aeVUVHVNAC7c!b#;7fHlyp5X&?)%k&=b1nh9lrB0D;`WWDo8+t zG3LtO$KXkq;UJAft35l&`Zd!)qazUZz9|LMO*#0%tPIs!A?oMQ8W8XEVz69?)A`H}mA zagNz_ux|^-u2x@MVUeM{eEmN(ds@Rw;RRq^atQL==Fjp!+9PTN7hfoVkXj;O~+41jC^v4JM zsHFoLTSv*^ox!M}p@wUUv@o$N3%&hL!xI-_eqhB2F2e?l8_9-@9evo9QOxexzF_(M zD;Z-9yZTcu*y7kj&+eNAujdZn_vk28l?p{}trzD?$P^6N>8>p6*G>y1Z{m2pHJlxt ziauL!;}%gn{H@dhd;ey_hM;=7`Ai;o&uxNO>yvOlVeR)R&05GnA8hP(}(+!CT*AnwkP~yR-`0P zQAwOyN$thfiYg+@m%>Qb3RqM0lcPIBgzJ}{#4!lbhcj{6wEXiRMzO43nt&|JDMo^d zNC)Yhwj94n1rqIuv+zwb8bs6uuy$4uJodAJy+2aPubS7eH6|8IK^XlsCqcuCxtz22 z9+9sRsW{>&#GT1@dKD=uJ6Yb$78R8HTOY@j!f zdlA$AGiXw*Mr`G@h*rsU-2TuX``X%IaO*JM(!E5rAF~{*Ydl!ZO-Km7`vZhC5qp+~ zfXcK;%=3-rypZk%xlA2=_LB>~_!8q5F>i9jeQ>M^2hK7Z>{$7lBxbjQk@8wH$`b+Q z-@!bmmP{N=3B@N-PBi>2pG-ChfQQR$p^D{&4;gJjbukxQ_31ARU*C$V)~Zm?y5I8@ z8NZJ{!0A$93Et`F>)4NBo;&8xl$tKA%Z6)pVD1VvuV%y2oez5f_nt6fk2EG>o4fw0^d-0 z?zaPGmL<`Bp{3;hxl&j%oXSblVa`hbuW00yiDAi8;rTk&=MIR$;(}Z7TEP?64WEEr z>Cdo#feD2EmO_nET{Me)1{-R-mH$oo!aO+9cv!m?2lVX#iX*9n(Iv7v>n?tLe-vIP zWx~0J7s?Ws%;3rWe`Iz1YH;Qha`Y~Gg4~p79L!pVoKKJOvt%3&%c;Tk*=4v_jJbCf zwL$%DJLUZ&$FQ+X6QiGaf%1fSta$$ygH4~IS5O+`j|=jW|C&?nH}j!;Lo8Owu%7jb zm9VGn00e#+#oMOIY-ZjMuf9m4{>*wJSM7t7_C=AX6YM-M_;`nHTs&v>a@9@ao&v>8ZVHpgjgW1MTZQ%FDSIV#Q(;UBGBg(XL) z!3=gruvxqqir_J?B3BH#JMLhIq7Z)p%XkQ|ymD)v06%1;0jK=fPIStI`KR-=A?mIe z^Rj$|s6S>fgPlDjmU2P+MGZzJ*ul?MJJ@!29M=4(MqXebNwW*Y!kcf|v+;u`tv3pW ziNQRPU+nHbM-=?)+(F}lAlS)BgP84d@}oY1b{YwDWjA(XREsHk92LeQ)~#PYgTktw z99Vk9jhFrKJ#nxuMB9{i^mJboXUfcPJbBhT+gW0Oi=b0^-q|6tf5Ub3-*p7TGY7$R znE}X_b;E+lEqHh3Ka@Di^0%vQ;6;}P$e-(j4WIVHxN-stj!WSQsT!6uIh}BPECN5s zEK*k2;qwws)ez0;S4s0pH>`Ulk8h0cz{r=4n6fsHm;|SR%6aC%?DxTy<(_m=m>~CR zrxRYfHH4~P6QNCTHO4tBz^1TlH2B&BqKX^Qe0~w@g9>t+U>Zz2c9hL6MR*%H=g7m~ zKXL446j?S=4kuX;fo7aK=!@8qYpf5&Ke-Kie_aRXC2PpJ$GPa3UWzN16NpxE1JTZG z<^>nR+ObU1W2cN74{o9D!AP1PF%Hid%Ry_~T|B>W8$1&Ghu56$k{Xo~;wi)&*AuJp zthq3M=*>K`_mMV_YcX_mB+uTXBC zf$su);q=rS7+i9jH>Z3zRLm{?e=dlwEb#($k36W8^JkroK@7ZDP5Wx^vb>8PoHAMj zfky-3+q{=F!-!=Y&-h{Tf*J^$`V$uhm*S6!2^bX8M1n>8V83uSSWOY(PHPOrE~`?U z8@3#groj1>8r_aS=LnCKLZPXFyZg~cYg?_4D4@Z2GCr#}qE zrop-4YTPCIhx9D@j6r$-G3V+95IpIL)2{Y{fUZAnXft5l^)mSR*bSvzlJH{gSzIvX z7)|54~2Oz&-1# z;m}Y>ifjSXADF=cEj1cZfuRVgWXphaLqF%mObibXU`XKQZ^&*uckF9&spK+-JShx5ZCq2a`4_!;_~vm(_1ND%WAJ>7@$ zKI_;$+nV&>7=W$KS-9Rmn3q}lk$3OG013I?3C|@xK=stx_+`63qWJBrnD%2w;(y!r zfTsLjT5?W^AK-kL1}s&8H6@Gjwhqg4IdwyRS0uRWd!xRgCvMd-r6yN9DPKDS*2Mq7 z1;a@=Eo1;ETv-lBZB(&hZ3}1%nxbH&Ais_J((^}GVm-@PBtJNX6A!(_U(cDdXlpn6 z`hLa3xi&ERh;_jW7r_JH*F59K`0@XWG5+f|h>oei$#%88 zwPrSW@Zwv}<$Ie*YmPYdS(L#r%i+{(Jt1qG8^HO4H9Q!iLt=K?PKcS|Nx#Mdo1OS$l3NF7@q9-dci9E) z?@q)0Yh0?dH3$V}ia>j`H5}YL2+^84N?kRgVCLY0-5Ud8=tmds+AtGSm8Rj=88&n@ zzZVy*Cb%?;^~?Unl7ox4pb>lj6$ovBg}+%>cWwi0+dhPxj$GK}5rw~NZJ|lOgh1k9 z)@yhJj!XS8qv18~SZW7Z2me6*pHS*NG!Q#SyKt7s7NYpF%Ym|z* zy#idWy$&=ke1ncVbui_32k*9gC3p>d=gm^cfKul}uxED#t>)e&ehyl^d75z~V|5i2 z?J5D+6xNLrX~0eDi(!pPFG&7~hB~32RQjMTT$v%nUBUSRHf8>t;hKB!>iSx28B2m! z!nJHirH1hl-|1*)D)c&i#3L3tB;S+yNfZS5>MTDp*T0_JJzNWI>a1ILY7G3-e-p!m z2XJVLHUgUmuin!I)0Bm{9fPkyrO<=am51||6A=(IsRgqo9jNG&h{cv4(evJe#Bjx} zX!waSGfkUuXz&k8>uE#i(_kpL%YpSLmXVFTKeTK%9~OOA!a1D|^t(w7tQ@W(8xOTY zk&hVoFF8$}|MueMtUtszg*g-cnu6Q>YFxn1g7+pVql^7|nA=u?na%=G<@6rcf7=D& zJ)bdrEC9FoCt%3YNigGdIL~iN1BMI#qt3KfBnM}+y08dwMgg+C!@wQh9^hq%P;WFkb)mlOXVqVeu-3#%(-Urlw zZG!Q##yBA{pRlMhZ`#pDX!v~vq=PPiv*im;mwX6rEPaWq5)Q%QR}t(^cm=Lm=dk&F zDLp(ij3(aAaQA5{&OY9cTjv$xzsgN8a5GF?q*Jr+vH;y!E`CI`3&hx$t}x z6%2%5^J4LjnI`ernT;O}UGW8cgo`ZavaRj|sIq)9S7tFsaU>BYJhX+wpO@mbrKxn= z-nT?Nsu6en5ahnMd5D2Mb!ZS(gj18$VYO`w$fiC6n_(qr(s{dkWcU4;_G?|kgn1$xwCgYBs zO7L|-7090-0w1$6m_1aBJu5RHl69tTuku1ymZP)Uc@+n?4C1HYg%H$N2?d7buo%C= zbW1Zx^cba_`gfom7>9w0s`S8VEtEZ;jKe2QIT{nh@lv}cL~K%}nNu4;|41Wq*)lin z<4Ra^-2wxPYItQ8T%7RH4dk9U&|eeZqQvDPRNhjFy?x8*y8MUmea$HR%cGdCdy*Q@ ztD`b;eQ;S+gexVM3!<5-oQsKSU=;R*YSanwCDV(PUw!>VKCR8cmAam=`gA`IeHkO! z%;~uMX$o?36xq)3J!4Y@Ld#%2?2wFwS&Wk!nIi*BeyZbWLO3`W?*h3U>7aex7hFX` z$%o8(#!+#`)Ln!0r<*68#d!vcZEnC&=LFbcvJF*^3G;vVO~JaF#>DZ^D!5(X1r4X( z5s%0*YT9`g3Tpk~*8I14w(C6^ZmWYGjNf8##s*4HK0sZwa{RdYC3DZOgBg)~P}_GO z&fqRb!v;^z>WV&2=hL~2fia50HHm1wU<2;{*#d1F6L98idob7LVRKVI$ToOFyYdm# zeI^PSAKmdo)pUGtC;(!2q(YPN3ouG>;mJL6z?3bII4OtK;cJ8hWWgAI-0FZj@2lW> zU=n0pjDR`MR-t54F{JKpfViq4Sny*z=YjtXc;^~SzFcU+M=vTM=vh0twZ#Y3?0hJGDMo8U28qy?6<)HA{lHZ5i4!ma0h2EuQl3Y@As?M1O5v&KnqA zPvjmiKsCdD=;~^Qt^cv_zped=KLmYXQ?E0b9kUxBb^7D<32ERo&y!bf^O;`xunC3^ z*P_*1Rh;xrk!BW&fI6l@b(bLbY@G$HHTZ&ed)~q~S3Y)rONWd#lgZ!MAuM|GmUtOu zf?lB!T>CwSkyl@#{;gRc(Do)#MEn>o(kx~=4+Et+H%vM6o%-3iWEu1h>}4El54>79 z$T~oi(O2CTbTnefD$0edF80p;Iv*@Nm2pdqK;on@JF@vvm}1{aF0NVY3wM=R9xXu! z77ip~!UsJZv*Z$kl%1e(@-evkcO`zy`3yHA!m!q{6&^|6f%RKTY3TGJ&O)I8D6uZ4 z)>0?wr0`JKOY>1%s}j8rn!xR@wIt293jcyJa=h6buFw|jt~Nv6%Eb^q?Kjas)Xi8* zZ*WI7%Q}V3SN5}5N5773#G>X-7_~h?P0(joF3;P33f#=x241)9 ziFa-mdL4{LMaOsuiCF|Mwu;eZLB%A$)C9k=y;~sT97*3cLmJx%#qF9@vF9}&_85ne zoz5`9uMO-fGhtDgIVx{`Dg!iEd4zMe{RgwgOyGv^FnoIc z8$UNpMt$8l@O!l%db_<~>biVf{KOl|Y`Q@#+Y2s<`9PS8JIp-QhWQDLOg}HU~Go&&Kx>Rp9yOEA=YBgLfb)aaqH9&X`*f#uypG$dB!qJUs&i z^>RS!f-D>})Q0P#wxFxA0Xt^wpjnKq*d+UtnjdeX8=WFZt5^c|Kkvt{Yl>i7<#QVL zFNg|HYUL>%uxFivYAXNuEM&&pvU`mH|3a}C$ZmGQ1CuUc{?kw>)(9nXrYv_EDhDm) zx>&%K#qQ5PdC^%oWGgbWGF~(?w^sQz$MfhPQ*K zlVhz(P;${8%g^i~YqsA4tD`>j@Vqk4>bP=F$)-el$W#qe8T0G=e8!{r-hegNV&Nuu z!d&_N7$m3#Kefy-?dwxqTN)0Ax5VLnqbVM~`~qGY$HBHK9b_Qi5L8seaMILU@J0U* z+Mes62e;Rep{gfz)~g?A-ZTOkH*Hz>A{Ap=tYN+CD@?Kf!gl39aof$A`K54`Bm&Z5JkEo4ZvPm1uOGTkzb7k*sq@p!cz~Sos%sX-z=tLk)@cTDh;LW zJ+P+g1I~QX1S(ELP|WU41LqMAis?Xna>-h zZD4`jl{p}=LV)|awGNCHIG`}=v@UI^!~n0qxL&do+r4(ci~9S}*`!0q9(Fx;1GMGhg$EAb)rHdHh zXGOQyxWNI}F;uB$d_PA4u3i5|Sfm#KFY{C}V@nX>Xyz&T_-vyEjGbP<7*)1Dq^e^(!uL_9s1uo1k;;Y?s!`)oSSzP zPTcAs6NCOx#RHx=u+$QJuWp3nlSQ~gj_s^RbercjA%vc&{zV?<$&;1?C-He&0M1pK z0}EpF@Lu+8+*~~yO@t$0K(rbvA6Vhg^ej%F_5cPcR`Dh}uY$9wHdIz}E3M#XpqJ!b zY%6w!$)9sUcJCM#zymgmEMR+0TYT($6J}OB9J85D!8upaWCo&ayL z)Mm1C_YWMqyO<13dxa9l(s=pscFtD)bk=-ugKVk$q&_$TW0GW8#>Eusc+tc`;tt9$ z(MK+S2AuNg#Lka?Xga?Zi)N|d_#*+nY3*&0OliP9#dF~0U>qI$DF*zsFYtc*1Likm zemRk2utPQv40bo;sQ3ibVY!8jzIn7vX$KY?G+`!H2i?toKyjfE|B7H7_~uKH{zt-G zjZKN{{+5ru29K2XTx4h8{iYaxxrY|CMd03WL2lxJJ>;=n?5@`iWOsc!tZv^#hG!R& zNb5L=6x0B>?+4IiAJSD%f1;kQEUeXHoy{_TRQQri9~U=4e|;4Od$_@A$yD}PF~(<` zIj}NqSgX+@atooDrn%0 zYjx8tr!(PUWg-ck@d6*XeTBOYN^tdr1!>=q$~Ytfe6Mt2e&@hn67lvFcq?Cr8Nb>f z_@D-+ylug&&v>w?ehk7L&f|mmJa~M;3=0c4!sdZ?PW^8uym({~;cNujx&_1ELRSnu z@dcHuzhc0JNc>xP2knI|z@#b-ikhV0cf)2le|7+OOAFzQz5ZYow3g~vu7Qu0t|+@9 z9D*g1@sOnh97syw+z|D}v&}v5Kq4A4wTf`s*cR&XcrWo4mBi}HlGuBEJ4x}Mh|7nU z)2#SCXuBkgK9zq+EM?|{+XF)!45JtkRf8o9O|gmP@ZVf-!uYq6 z^I0t%?|9hI#@ju(=!+?y^x6!Whm4_SiZI`H^&r)#j0B40j0Cnb_LgAo1y3p|s zopDkcKfiH+#B;obkI46t<6GfqNq4HSo}9{aKtn zv=Wo}j?_7(6JJ=(=9GA~kpe$W*kaTKC$tvf-`W(?6w8CwJ&t&O$RDIzzr*3M6KJ>9 z7gsg5V35f*sHcU}KPY{(Si|{>Owc=FCCFr2_8*F+UiP&^|s=UhqzAKo*!aTMU zXFr31paZm4?ja-_yrE$izjHcl9ML}eB>jFS2qhN0!7cm4S;n9jtuMFXH<@H=ut^4Q zx$H#ob1t-OLM@&t(!d6-zj(3Ihvj)naBd~#O!l2f^^Te`ZvJ9el^(=%-_ef~RR#D7 z!qr%MWHlcB>jE`W%d{>*tICN{tZjmeYZ63AH?7K2W8Ky zVCpyz(#J#~(x4V6rv0T0(S($n?U5Z19jPWV4JWUi#E94mWt1Y!^+(ur;Q@ zPrL3EtBD%TO@7rBy})8=qxqc4;{b%Bz1 z?wBnt!Y9Q^^mpPRnxTCRPDh#%-&TL%KP^L3ek3@!X26f#Lfl>lb&Qzw1s6*gGI#4t zqFrZ!uk-4#Dx@3hiv;;wo<-n#g#u(($O3c&Nu2%7$y;5@Y}0UMa*4=RU&* zCn?zK9myDG$?#dC15B0N@RL~-C?|TO+FVn{W`97=#Vp6~8b5hCiVHa+ea*Oq|A}Tp zC*v{BL|v-@L|}M?Te~b!hE~;qhOu?6$*~GKxCFA{C#{1?d*(U z$EZ9OxqXHKi%6QNpFzJ_U4)7GCwTMPML7!9pQuM6pYfN4_;0ML=~Uez9PxRnY;x}m zZ*@)%wjU|u`M%2rf3+oWq3Al9ZYKaw)7?OA)hie%bcd2854Nkf!Ny2Wc+v6>uDou7 zD{-5Nm{9>Iw_AfmFJ|{h9%GfMyn#W@xg>teM>M+pmc73tG4SdQ(A<$rFI&Gvzda_r zbsQV0&)7h;jqPEbKrIB8WTINs8fX{u1(C7Sn6UgC^c)g~BfmdkX|xXP+@6K|-iYHo zqd;&pj^kLBb-{qQCw^$+0IbD!{UMUm{9RrEGt32viOrT3-vmNjAUj%EncsK9=shcNzxb%}1*qDD43iA4_^O|qw{d6@qPbzOGwGe z9+41A2zBo3R7hmzgKP<9@3Kc}kt!OOdqa@BaS&h0fFc+|PBr z->=sc66%wKul25@2w~l?d>{OB?h(9{*hr7gy8sT8z0ja2i8{(>pvH67q1tr;%rqyU zxOz7njtV1jKpOj>n@sW%cGHAA#h~v z7`(G`MxlmZN&bDuv1R9X<(ZG|@u80!9{aiw`aHtH^@JC+NcA(Gy%WjTbI1R=s2U@; z!qBDrVA?fCHn~nkvkY6Ph#0}cW;ems(wqGrnK*uaIsD3L!u7fW-1q}_RQ=I^Xmq0) ztOxtZ^dfy)kUb1J8|Op7n=!^9YalOnF9Wk}JSecYV%?VDR_!4 z1NC?!X9u`$jz>59Hd<4rjB`(X#`pQD_@j6p?2r2nfe*f8+5E#~Pre%4%eH{#w@oN8 zJDysu&oyx%;0ryLJqHX}Gqu^kUBjYfaz zF7Vi%On;4?!*xj(uvK>+9LdW-!S=PxUFL?p%gz#=o@ZEn^EK3x#f+UH$lVjDgN3<5 z+@je{#Ne72i9PFq4IjJdgUEFlPUlzo)sQAF%!!t{(|XhQ&{fXoI0E=Az}3# zh)!^WjcotZEouz8l@)OOv><=>u`*bCs2WwxBj9&x2`;xOhj=@2oaQou3rhZ>OK2VL zl>5XoBkd60wVwVII0$KPM?qr27tm-pMepy~2SXhetaox0qe5ol;A%vL+rM!z?G@CW ze1WU{9eJhodJq}=k<`TL5)mgaly!~+;h+%6{J?`R|OfA0eWFCuW-S{VQtLB8RVAu?rCG~8(%r{-ev zxOPSymTL<0wTL1m`b#D9K% zcsFAqSkF>`L6OzOUZxwgj8{V4X#u+RtOt<`odpFG17YziIn-iZh*S{~K3>&^Q*|0> zaNZCCMURnV!(8M!3GiM1>x8@KoFL9jA4U^x$%&Br)Ry%|58remntOUsvepGQ^@L)+ zhZ9D@PPm-Vhlzvcu)c})J~jTJlvXTwo?={!oN5f(mxIak>!FR$+#HngjGh|eQ|C}n z-_NoN?S0rg^p1B+o;{n^aabZ22Ik4pk#A}(B@iw>{)aGX}6rpy=onsJpAF8mFmpI?U-JtgWk<^>0I$B2)x6SiuODzAAj z39jrtMiP9ifV^9@Fz-X(*O$ zN)ODM1i}x_!HMn!jM%>$j6C;oRD14Y0PE=K>1E)fk$9?H!ZwxMR^5(5YR8Cz3a!Rci`Poo$Ikq6E71+sUwt5SJ_0jq@Cu zXqWRllsM~*V^?x9LV7q_3#!pq%oJ;98dACWBXDOwm+0hnz`wR8>Lq6X{$9O(J@4|TdE406o1Gmjg@bL)2tmqDKEb)VZ)>dx1iYQrVga?M1)q92ua25g3$~lTswoJ~<%9H_Ts*F@72y9ue|+ni%hSw0j`A0i z>CQPBxUn$_6~{fXp)!c`WcCJ_aAp)7r}IGRg$SI;nuJ=r+3>|-EtHKhXUSQ0{B_b1 zK3Thfr;|G<1cza?l_z?L7ofR(4fL`d&{o!wXc+9o)a|cfuapyX+`9!2r_AR4$8$x& zLz*NZAQo1hpm@32Ghzg&hd}-cs}7GdY*Pe^VMcBEqfZ>FVszQ??>XP8TRP=Q;iA+ zd-4Q2*3ia!3G9)0jeh`7GdtW5Hnaz#PQ*O|G~oze__ac0akT1K@PhM zCHR%&wPHaiGYr8z|5nIU)4|JM+UQP02W%E~2G!sn*f_ljw*OSZvJ)$C;r&$lC) ztQ+$pIS2*FXS6-bxNHU+L2=*}NdNi+NiQ7G?89HM_@~F2@9T(D*8_9V?17J6^+;Tq zS76#Yp5*NxQ2*GGXq+-(-l|aGj!5wom)9psjre2WSP(usIE0Inmf(^bR&dNz9(JyM z5ByUS@Ygy5a<|l=q@*eI-p{+5>h;#fWnBcD&6gh^eg zN#XvPpq7xCILJC|hhN^~jJW2qS@8nAexnNe=g5JW-g8)A<;%Q<1+czt5YuTK%gsdK zJ<)4ewJ3?+Ulfc+NtZz6LJ?-&%Ycw0B_JwMj8UT9a4gmt8VZvkV45IaxtkB$I-g@q zq#)lr%z}(f;KALA6pO2?Y05D^+|M|T2hQfgKSyD{zE2&fX6=XP3C!Qi@(a&bv9ofY zFu%jC7gM7Jxz1%~z{|J|@Vyf%y`@Q7a}OBT`;f{1+= ze+T?`eH1k3zsHa*#>6gq5I?RrqBr`^k%5bUaoN!aSmhW2$*)}Dra&V8@v_G$8#8$S zBL1S+wFCH=AB9uX6L7EWGKkt54I2zIVD6<1{J5`M*~@(a?oH)mY+?vXns;HD#zWYh zi}=$}8UxhJv7z<{377T2@{m|s=xK!aZ)U-Qlp4IUBa)*U8w(P>l4NDED9JN_$M|ZB z@b=$(aJL&?%=021|D2&`f(Bejxd>T(#;{u{1`gKs0G^sf zV~-pF$zR3PKS~s0Kd%7({4x~yR!!H3#E|F<{a}0XAa3u{#5)S+Fx_A(RqKBaN1r`| zum3$HmMq_6bS@vRvA^HID`Ecn@%LCUGaf>3?u77CKX_^S5Zcv$qQl(~;6IOm*T2GX zE}P3loLB(g9;y)yJLY=u{|O8FUm>qr9yC+Vakw%GDqHh&Fx|zU{8#D%=4T&Kp}DK* z{_b+{;*Ddvr~{m_TZ}(E9dOT+AQb#l3xjP+^pBZ6&-bn^=ZdQkfAh3;5Wv3o7Krk| zX^98EPkz9%5miK5MHHmO2I;%qE%esYAo#MF@`e-})uTogW3ovx$CYUd?ps}gNzp+NM|R<#tDoTPK_9%6!WdPvzru$Dv+&LB zaS+_{fYYCKjk%SqU;+OKZuR<0x13BP8{A)GnXo8syJCrYQ-!$skq0`XYk1mT(05(I>y5MZjo8! zed#@%o$CaiF50lpX$*cuE&|8v&%yT7N|4I0K-6D=mK_58DDd1T1Nv?iV;AB+b}TA+SEt44<5{K({R!SeB7R z3w~0NeSV1SjP65!wGxmX7UUY8^}$J>BJg_cRS5aYI*xM$pzF>N#xhj^4HMQ2(duMg z^+Om_`r5;#HGKW7*&ru--Mvy{%l-XmW?0$?J@6)4z9Fo$5HuYaO<4|mtVNz z<7PWNyE&57>k05r=J)X2r^Ug3mK8sEZWatCw}IfP0vLL`l%DN;01d?|%)w>Mxg%qO z3lAN`)^$?wu=70}o^AwmQ8T{HAHWlj_P~|EM2uVKgjotcIMFu)V#A!F>GU$5EO!8N zUS0t0qU~hp-4nF@>WgBIyU}6hYe@6_fJ(9bFjG1J_J52+&8|%FoO+sy^gN=j&FSc; zunNj9GuEK=Cir=<1LjYWM_)FNS{N$Ce`qoS%Kam7be;fco-d*g7KXvKJ8ah#JO{dD z4w1k4l@OxV35PZcaF@ObB#-{|@^*!ZVT7a((uy4T5h%#NC6EMnJ{yysuuzDQUV+v3 zdf@zJbB+S*-sitU2%VLP{+pX=-S(5<_JU6*6~-qNdf1`eE)VKx$#|9#j+k=F3WHgP z@6!=mYX7GMLY~?Z$1fFdPPZC&wf&~IbQ*B$Xfo0A>j3`;yBS|=9WLCxfc$CRNMDGT z;%v=O-2H5n!>>F5_FWfvdzxf<0@Lb|zn#G4^Y^Jj)DzNP(wB552I!%)Vz@rh0S^dD z60<#DaY=nlQdjP7=3iyG;~DSZ^`~&OQPU-^{l~z6aU8yn3We{Io3ZtDCT_XogH`2M zVZ)gp5Xe|V+p>D-{44|3B`(FvS3HzGD+J#x>+sa-MKt4|CVEK5Ly7oeuvB8XtQZQ; zr$tb7d3n;48z1S-D;~IX<9%w;8AiWt2DGf7M3$^Pi_6nCl1mf1a1LLXzhHtLDoS1@ ze(@aiof(L-+uq<8b;fe$kD%$jlbG+8g57opXk%v?D(2n84J(d<7xiHr`96rxdIET^ z3%tedqv_Q_=x(xwBlBMn{jJ8#5Ag)wKKqDolm)nn%jV)<1IB|k|A~n!S72hvI6e(g z!{tpK^y+mp%zEL5#|v4`t3eyTz5jyJWxsK|f*(46vcchpS@^9Zk=i+|$Ap*nATK+L zb(Jh&#Qih6$Z5jsz5*Pzu%IU|o73#YbE)u5TWpC9!H>JD$T@?0x=^$ebPQC9*~(bF zEZ7aw-Tv_BP$A@1?Zrz^BVc+&Jyu*hiDmpUno;FWo9}z###>F$pBzavH?jNT_ZalA ztcB`uA7a|V7!7T~Jg~07P0Q@z*-#hZU6}s_Y>^+(VZ^2XZSHgDRIM$19!kc;G zpzm&nRRcW`6J855b_?+LFHOXQKA+G~F#$}K!@=NHHQe}Z1~M`NsLPyha_jqPXsa)8 zzpNq*>?l(?YyX7t?Ni{w1{)%N#gIyjf5t;!F3{amBT2K$9gHzsiXv&%D8|*t;FW6h z%?2SnFqQPf4vF z>)(mzl9LYou%$T`!?YN`Ge`>lo?<(|qi?Z&@fMm~NWm~X5`!}bK+C%uOjKjBDZ>HN zY%j36&krcEc#ICaLm4YIA9ntU#Nu@y(D1c0_8R%HeA_5g-l9+(c^x_j(m-v`Th#a@ z$Tc}%h!0HtVP`@S)^W#i_D~&K&X@vQZ!aTzYh9uLnmwN89jD{LGE_Y7Du!k(hUWA@ z&cVH>aNm^Gyq9(hh<1({YKDhs(DC z#|NN`52*C3ie9>F2QAx@$?D=a7~6Lnt6o^(-P3Fa8ARbkxe#~DyW6Y5z8kl)sgG+uQ*UU8fU$L_yOGKttv$CZO&P3RjUVEYE{J^O$+Zq`G@BnP_c z`%`o{mP;Hgsz|EHa{5cb0$s0mQnQJ!v~R@)SiR^Uhqr|}79M)zO>G&_-Is=W6LlFs z(vlVj#&M3x33HPx_;j$L4-Dr`0++D>$hB~W%vpB$Jmeou(0h#+99(#*;(;(n)f6Ub ze&%hOx&eY4f3o{966?}UyqopWtS8SS`guoj=6^?#r~CrGZCMJuwv`+ymOHR6?u9w; z{(w7W9J|3bCm^1X=J8DwB8sy^}slK=km>V_Y)MhLSnK*uLo}&X;?GdtdB8J$oZu{_X}boFT*?aw*5-#lCpr zrwEeAqi`dq4JS?eMm-|lVx>w49)4kh=^dds-Qg2Gs@x8G-cInZ zmQD2Pg`ykgDAjJlnWl0Wo$Mb&pY;&c?RkZMZ??miX-UxYJ`v_TuE&!*7#mA<0M9S! zLGzafa4>E&P8GMLLTfs~Bdr3ahpfV)!$TmSa~yMZl~wlUMe+O#WpUiK5^UTzkuB+8 zX2h`&2yn#$_c+z?C|C&YYP z6?5_Bqi*6y431iWi>d}d{_hYho_Yx7>#xJFwLL1`o9=Mzw(Z1YFBX$I*3Q_OXo&Ns zI-*QlH;4PKmP|N!0w*8T#L~ZBbkIHk8jgK{m4!yQXKOyp*%<&bPs*TNN)TfVd_g#q zL(POo>4`~QXcrR#D?Y6tDW44SzF8V<%h-sbJ$iVtT?_W#Nyfbo3(@cQWss6>0Jr#f zoc~_}Z|*6in__bD`d2%)i;G0FItjYvl_;tDxE0NkEkKps5!e=-?z<((uU#FDq2=3n zowAG3`oBza)3Oaqum0d@HA^x^+h1BNqJnapUlZ9U@?=)40%z7p1MIoxgil%bXu+f+ zEIRoZRxfwK-ouo0p`s0jd|R<|zZA}zn2OUAQ|aPqY$gWRnEP`araKgnX-;X_mN*w> zca)NkJ9=3U>L=W?Tnh7gQ%Ou~E`C-W2aONsVRZ!IZQ*qgwROtKt9^s3BsP;1Q_|qx zqy-o)_>hxX)JWBmr?Bsgn{X@X6;4hvrFLxmgQ{NN1wWyXK>pe#dbrJ8`9kuA?Fe;7`>nZu2X##A`k684?@ z0^2H=!uba_FllBWXQ(0<7JmH+o{yu!=$0_wL&K1EN9n?T)?;mJa|DUcvGmW$Z>+zk z0dlW3QPqSof-TR1oJbMQzaq$mqR}KW;Vt>N#SoLzoWcCOHK;`=@MazBhG$(uAopPa ze>F_NQ@gL=s?1i{;A#m@TNnMGFCY{|ALqOG%kTAV9yghQR=-2ND!Q;1S#XVa*965+b zHO=tlZCko?aV7AsZDS6Q&+xqe3iyeMVrO|R>@j+P4Tr{vR%kIcK4!cimfLAc@qp0A zVyp^Uj+=K%aJJmb1uxAZ^weUzkN6;zw)R8qh)S4=LwGLd0+BNn;Lmk@5Ana3z)e{r z4376>?`k<{uS}qmoZiEt3_-5m!KL8hQcDeXpF;mTmGI!aGG;{d!^UIbFs6DLE*yVH z6;%_cl$8&xGjm4WXX_zZHvlcmrEp_yH8H#AMqXdO2~z*E@TN%=TE9+%fzQ&)I@PI= zQ67%hdE?|-r3s$cxe*21<3j=!Y96m=o$S$Sb16m_Qju|4K3avDl5Qk zln>;{)VAWmv3QtUXbRftyKsCG`~40lp+>I+_HIc)!y9p^nA3@FPu{_~t6M2olyMjd zn^Bm)B6nluFu714MB?tVEP6MJ91CMC?{GZuOoL9ZJdDOJEAXL29+9+mgF78|D0T88 zox8ve2GieQv=kThqdjr=P$0G~WnKHf!rX=#>xq0)1`)h|9o)OqVdafc-nK^?7-#$x z`RbkMxJ(IZ;_d()u7=pkd{}y(%>-+s@!;Dkl5?yZw>ciB9g|Pu%e93NAoLeBhks-L z7e{FR-V8%de{fNF2YtO<6NBd_C5RUaa(y=R%+VR*Om1?+sf0@_qJ!@}i}pm_8sW;}mPjQyg(qoN7!9+#!wK1;}; zv;x4EC|s^S9m8T0QS3=G{P>Th2^GrW!--#zah}cVj-DlX(vkRfIge^A`An{lnd3z^ z!*9`3#G=qpnDQh04{uoXWEaSBQcLT*af8gvFF~A(ifh_fOT)5MbrxF-Sq)eQl{PZ^_O=tk| z4|*8F^`fn^vKVp51TO7io#B_Pm-6BzIbQ!3lIIuThO-V>7&8%tW2@-uqBSTpqzQX_ zT5$hUISe@DLv>fZB45 zFXAG#$hV~i@Hp>e%vmpcK9=HYG7TTS60yRx^fWK1(e~1AOnbc;7Qcwc0hNeEV;Ac5h!W(V{_DR zBAigdc981CrS?0uT-ysDPghXcZ+$dc*oGXuPyw6V*|S?X1bZWyH)h7vq>gqq&?qe= zJ0AbV&^HEbCOL+`Ol)YyVV0lG%*H^;z0j7l5jCuSLtU{OUX5+Tou>u()w9Mh=j#Fb z)7TYOKD47-)n1U=PH|pc$4`u%yA)mV3QFJBCJUU-pt?f=Zv0+>!Jb0={Pi)=VQqqG z#mhi^sTK4D{Kf3(zoboLCTHW4QJA#Z6>bb_!mmxXoJDWa&~mJctg+UGUwV76Ts9ov zXZhpWFk$X=i7=e)W&s}_nUY<;A(ZPC0rG=;$dRaaGFQk9TMn!wyPp>@W_l5{qzA!M zBgWYs^upF>g_ym%91eXui;6eaGe3eG2+c4c1*cM>$9*vrB?W;@tu2w9Bg{W~OaWgl zV_ndVk|d1l2C%J!YFwl^?cr}uj_7Vq$a)hDuVn7uAUhy3&tNPUY1GC|q-kLa#>DdWK9O$Vvlw;> z|0UbRDk1dnKRoJ`L+1*;;Ov?HozuOXxje$&gMMZy))zZrwnQ|!8T=B2MUp`w;a}2p z`)v@sSQd4@z5$2NALzRI_4KXd8$zp+=P>-!-t zcMzqf{)1~Gx|~PKN@!^D4x>F3dC#kNqlD!sHbgz*#a%N7`wjUZ%l3%RZKEOF#gTo} z^s#(Q8Q%AB2N`cea8+Wip2qLcxQV?31|q3I=ubT2?1~D)j|exq98=%^K#t81@>9qR zjyCAP+(n1Ls#zGX`Y!#8lMo*BtVD2Bns7Wm|C2)^w#g@^XbQMY;?b(k#$Y8!T<{04t) zy5I)-FBWi=ONIGTQPc33p)Kw~E=Xq&h=Dj8v-BRep*fxtqjljJ%m_#)-sf?Yd#Ekj| z{B2W=y*HGwr`<3~cugXFC>{mzvx=x3_Y3q}%HXPZ9g_J+Fv4K~)0=8=d1o?YuVyX; z`J-^hx)4%5%~^icp4J)qV`V`A%Dm`>3Z(`Wy3!E~)f4Ghi7 zee-ZyuDA%4k2Eu8RR@CHcZgZa`Zr(?I_<+8I`gk`+rl;QT|tD@Dm;O<{8-E`+DRV@ z_QU7eb}Dp^@ih)_V4d=D=Bm&InTuaJ*A?p^_(}?D9^H!*UI_5Z-RI!&Jz0GI&6Nl$ zG{BYH&S-va0Q}P_JY2!LbS3LCHkoyX*OtSv^l+$PeIheUL4M$cuQdMpa&nhBbexmy zaMhPQ+P$t8R_eInp@)75yM@6%_W_x-VvzXwY9d)a8?_!j#7LehJX2*n=#3W8B_N5< z&*VXzTs>wAtD&jYTUhrr4J3!IMM<+I2#5XtbX+>_<~6X0yLDp-VzB3Hqi^FYoRwx0b95!|yF9mFz5bK`lnjPIvi zJO&L7J9@o2kLo! zoSv`)yUm+H#Tm(pfnqq~UJJJsSq_<vATfi7TG@J}KGK!#i@;+L0 zVh;VOWCQ`MPk4B4D0;~0kq3>XSkCwl-zWRP$3?e5PU96m6)532O!UC$bGB$ATZn%I z2Qk#phnfrAg~ygMc=fV)Qe;64oXj3Ux!4wX;am^zgX+kvjsWr}YaK@=X*=937+1+S zD$M7Fi9>G2a>$F(#4AxVaN_e2#wH%Y&Eu_Dl;VY#WXm+{54Fnmjj? zMshfr@!SLt(uk^H%x(* ziB4v}p}xHfM+4csdC_|a5@g-i=kvh&_Ez|O%!_6mXvIVyYqXDM-*k=x7%p=g{#m_& zx&_{NW)j<3JWj;|KXIZic#U(!Pk_5^eKYL2^pyEpbAj%Kt*Y0s!mSrh zHqXMH^EQB6LoQ>Sjbrq_zM4XqW(ChAWzSdXd!;-+{L?y(m*c1Rg}RvVz>H78KH zT?pDWk`P={Oni2A(Ivx6Xr0+o7|4tP*^q^Jzy1$&cx!Ko>AVJqL&C^$*0GzDZAnh7 zyo_^p?ZAbWUAXBzsq1)T zp$Ft71wdx^9jr*X2KvvsvFAoE3Li+~OsjDRjfBfM_x>ZeZk+~7H{(F=v;kfyQiXT6 zk08}l9JZB4@ai^f0V=19W@X{ChnlN=w4recmv0R}Q>+?FzC=D@euP9OPKO;xyX?P_YXeP~kn} z+T3eE!$vdMq1FP&!oFi(ggO4~3WJiSyHsx12w2_!jG2-)AQr%8c)|LNHEs$2&1ppL z*EINZ!kJEIdGuML*Kv*sJA+?cCY?2@iM3qb+0%ek0hC}-NI@8GMa42o^JXtliv6wb>reslzt^nRe?kfDML z@63iJE9c<7g$YFdm>UK^Rb&{jE+Wu!8I_e;H^)sI4tHH9CMJF$)DQrr(&_ko`x-EM zIgWQFf>{tgje}ZGDRge^Mc#!j z-15mDE!PLoRo)wk*64?P7Vv#sN#2#BNPE*EmiNcqW0gYCP_h^d%am zd04T|9BlhN=uLeAZrry(;ED3^@^?zE-&zZsE|`#TJtn@;biKdvP%DJ-eU3gwygF#No;n zI67-HT3s!KUst?2=Epa~ch*b%ck3P2&$Yoq#%6X}Sct#fze3%&L0rv!PLkQozVfyZ zH(JLMwk3bVTxkm!*5Xl<`6YC{h9zu?>rlze8H5jttf&3oBs|GxsVliZAl@Z{Og>{v z7ECjT6OuAu=RJ>C+i;zIe`r!c$uQ(c_0jyJhB#3m26fWwN#(R&v<-MiHdZcx0`oaE zLze@cTf*Ua@K&6&UKjcCLR>4gFKB1mPt#BF@noj}cM;ng#T#T|e_sJSjM4#(FJWN% zy9EtiS}XfnTNAOAQjm|~b6T{1(o~CB82r$Ki|&1;ywG}3f8@dwGF$`|HxICk&?;1K z-3v2Ey8z2{aBw7Sm}4YIyqEM{wI{0(s@y#Kc07KXkhXBI}YtGT}Q+ zU;ltPBB#+1<4t&;R|c`K_VUEl3-EPICkPd-;w`#kg?ejVlhmMFc>0qn^GBsY`Kiq) z;GIE>n=&v?pb2bS&(ofFckxKBBh3C%2tHcDtWTPW$2fCQbO)c-kUF@WpNOId+d0d1 zSteYp7+#-Qj=r8(FpOhQ(p6j;Q|Aw)7e7FmRmX73r5(g>MLh)EsetC13Zn9{2cP?U z-~-KaT;%fp0bQuCmR3o2B9sZSS&pbzYPDf9P(F4puYH1vIESW zg}C_B2Xyt5LBixWfcQ<2QIg`6v<4yHpZTLNUxo8iKa+hKb$B7w94_6M0FsF{P`%_7 z_!K|GGv+P$ApHa?gzMn`+oO0$ayp&BcqekEG0e+Qi4lHc7&CYgE-vsw0i&Drhp{mp zVe{bLp9R>b`h#%Fr=X0+5>&dFNpgJavFhG1an+uLrWgI$-FpvydAEZxb}m7D$~;^- zJ&#=4ejXE~GO@tK8ROF#FC@zp_>PM)%cBNffBgiDB~NhTodo&k!tX0P%{L}`rjK#_ z!!0zM%ozV~Ldk?m1_EmvfHeYnSZX3c&Ky_g8J2B@CQ)a!9=L&b$3{r0dJ)KW^&@3&epXq%YBQkG9VmQVu6jJAQx$Ejq->JMnAor8`s!l0_5 z4vxEIV8e$S?2gmQ+pIX5m+1Z#w_4Z0I-M4@t=NKzYivpWQA>o?3FvjC4V@mf(73eA zpt>&@%$3CPlPt?&)gFP>P90?3zaH2#Q60q(9waz}Wf%hI!QlFbuwQ2vxDJ%Uw(E)b z`qxFwpJoC3{frm~hB<=1Iz#yBJ;Xf43b&qjM4tr;hqPT$|ck!lV)Sg4|NxD5IwOt_fIT|=$-JK@iaf5Fc-RVtV4+s$t zfV&Hyfu&C*k{`XeaD@(jNYBOfx17-Zstu|vb0R}kv*3VS7O^W*K;44pU@vwXANX3) z_JLeHc6%*uaM(<2erbYpQz7ouk>S039s_AP^(5+>1r+O^g%YDL)HZ}m4c7_tqqN;< zby^(ix_e>R(vK=quToLR+n)Nq_XFcvBeZp6`Tp2tw5{_tp3PIkuLsS^trd4rz9bqn zI-=mpwD%bJrkTpgW?|0>H&UY?3X=zO(Wzt@NZM6cx4e~}dliCr)~l#Qto(x89b~ZJ zGavU)O6LvlH3sfo#$*3)96wJRMHSfu9DA9M5+glu;-WJeFn@9|F`eg)W^3c{;I{){T3wI7Ru_^ZpKrp1ONzwfi~)K+`a`A$ zkD#Z_H!NIJL6dC;;fF^k*j7hl+Vy(878ir57F}pkXGQ)!@x&E3wm?o>4QgL)Mz2Z2 z^x<}MR1|51{$fhAgsSdB<$F^Gb_{1AT|#zp`dH zGtC|23z?I#s+<0^Q-I*PZXB2A6QGaH(q?oNp>p926iqCH9_HV2xHtkHHMu0ea~?5d zvjVcgBWd-YGPv_64@sgg#J+aG^Imy4i`|D0r>oGh5L2q*+)E?^jL`Li60BJChZDb^ zgDEq9(<%9WFs5>bcXY!yRBLocMH5FDu+9gQEkAKNw+M3IIiT9k85o(;3+KZh(DmQe z!?=GMZR+R3y1HMm?D=|5+RMps>DVx|{ke{n@0cEZ$PzN26k^QI?cnvE2XUiP5UQht zMshz;vid*tofZje8eQ<*iFw$%U>_;FUO@}f6KMDxOHw9znj{heFFKTYihhFJUZXKs zq7uX@y>+EefeU~TNzV4^ex?eFhJfHTnv-lB_CN+wJe2rE2 z@uz<>_%sUe!M6*pZA~I;me(;)*$cRDH3x&9w^4qFHVJW#frP>qNH{f(7;5bS_Z^HQ z(hvdTUVq`aU?p}8n?Ul;XkNy?T{y<+RZ-CU%`sxkpOBCsvgm3RoJncJ6~T3o``{T| zaeoiihc6LxYkt&YJ!XHJ@e! zW3{4VSsq15vjQQ{upYYgU*MmMuW^28I~6;UKxOBc;hNV|!O!9(%==;k&*KHTVrhI7 z()f*OHLHlpjJFs#7{g}I)v&O51}rtPg00NIcXnklSh38DCA3rbf)adgunhv+h9I#? zlJjTZKFTdNXZ!{Uhg_j5$o^HZ+J$=&Z^MPdVv}K*A z893F>0wblE*W+mm9EeNCZzXxKtGa}SEUAPk{dFkz<|%uhPr#NXp%^E@!J}7#=!plv z=^OTKc%a3e3Z5Cq%?I_s==g4U;aX3W7WZS+rcdxWOB3HH{q zdX}uROI|yv-v1qZTX-FZ9?zniCTBpYV;g#H_yu<+S97>6Lj2vw=0oYTEY@=n;twYQ z?wt^W?ek^v$EqBfwAhNWEhkE59Kq_NxhngY?xe+rpHce9D`=7%2B};(ta6Hf7oT^qqa^$iNEIjB& zw%WXh8RoCRhKSHh=j(C#U>xSWJ&9^V_IO*MAMI}sLCU22&|k@1jq~HcY(YNZ6tWrD z-8pbMTxQR2%uEV~s6e%rFq zl9z$pgnVKDh0#Rj(F&| z(8o(f&bZIp61NM#1=UVhY@2NZFE@Lkn%Q~IMs*&Y81|O9EK)+5+nx~pE)cKXzlGX| z<^lgNK87RzhT?eS|Y%|{A4L090Wd5y%uAm?_7nI66VeHgoc+0X$ zm1SvIXjqSjji*r8l20I!qX><;Pp~R-2}j=E6BaN=iT^esZvVgaC?#r#3oj7(l(`%a z-th#vL;J||3wf}6l^_;vjppU9b%BBj8=*sveTS{SiC_0K_J*JcYB=cdM31$>oKA1# zUXsCG5j)AF5*yy0j`vjO&uly-Hptjki!o}^PIMTJpau#BaQu@MPGY;{FPs3n^vN#D zSs{kC)`F;>I6@-7x1(?~<6*>a#f8gC;rXW_po$?7o6mBZ(FsWpm&C%|*MYP{!Uwh9 z8v?H)3Ensm%uk!m8yk2@C+aN+>BSQG&(Iu`jeTIz;V(!#y^wQ9TU$#09Af-1bAOzX@|LIEQN&TTISw0=GMyF?@(RS!*yhCKh`ni=j)&41%m$$^L5>aP|M7LZ&gLY_rKBPE6Y(uSoxs_ zd<2_4!|>kH7|-e)1d=UA-ne+7`gCWwo@<5^Rm4~(tdM5^Erf^Gc~tf5VU#R6iX#ez zB;q7v0T(_-v)cFI@thV&hD07ZMJW0u14=j0#Rz!{)xxXXBJY|DpO$XBZdj#`bJMzTH1xGO{uN{pV(K zNd6ksS|<&|Pq*Nw80PBfu*0Lu>}ND>1xS_uLa8&SVCixfZ8p!`FN zNIyRUTGCgrZ9*pO3t?`=zG|Erxfo<#l#{GeUZ}Qf1t<^8KvDV$@X9!ew#^%1!+Jsf zb72z@;Ft3b3Xa3g{tqx&^C7xCUyac&cCcjAH6ruSB))#OG1MgRpfSLc2<$H-A0xP= z=8!YbTi+O_J)c2)OkRO)5u(lK5jd-8f_Zmjz%QsA<`){k-`Fs`el`fywbgM$uNe&V zS>cVF%v)dd&Ja@&g6cZ2(sidRVdvK&Z3VdI9;jt7C$e{P|if24@?OO$r zZaYEGiOP}H<%^F$YTWLyuX>xOZr=QyS;bVH-&3()hio!aF& zLGB|L-Xh~1k}dHWR=yx~*MJ_#UYko48rfaWQWnU?ZD98%7Y%Qi68b9|jkdpr+DAIH zqb~%PtR9L}A8x{VkB~ETtWGt(gzG1$^hHh0dBi#}n{I?fp zGcJeYvsn;msYkmuPlt|R)<#a4kA<$jjG6ulzF08t?)-STF7^PM7qz1L(P1hk6i9{c z%i|Z%F?#p!C#+_7Mc$kgxH#Vij^;_D)#l@{R`ex)WV2b74et0*$POlM$j0vilCiCoQOC;vRrEtL>*Q6lJj$YP5O!uAS}?9x%bA9_v(0{Z&m@8K>)8b& zG4U0Symv>nY)x35&gZD)`QrScI9{KcE9yR|gL`tq{QK?75ZL`5kCtqPdjZMVt>g!0 zsT~mfyAoBe%^_2^^+55%KREa-0~2u`d^|ZJ{`SGmWb?B&;1;%kpk@rOum2g;Risg^ zCJ%CY3UiHWu%1G!0v}#Qq+5eq7hBZ)w3A%{@aJE3Ra_qlQ(V}pGVG! z=7OMJ2rThh5x=#p2aH7lhlR}Xs@p7FbXEzD_-J5lloIIYoQEX!|FFi1;`JY1;ApxP zL(WrD8`uSl#7FR@#w%<}sD`?e{p8P#*_g0olsX&!z;(L>aAsr$wr)@Wlga(0&sLb* zueuZ4+(*chB^6*h_cI#99-vzVxeCf&F#laQiav5A3B!|6?z9kj|FHuc6yhyLwReahqbm4#WvCYs&-r0ekOwMK9bISsAJVVIXH zg2}Tj+zr>Mu#j>^HEW-UfbMvSOT`x3pU94ZVKcmYwa5*mJ#s1nJl?AB_d3-#iBn zBFPZLo&ot=wvaaq_0VRG89t7zMC+)(MlujqkX;4O}dMi^vAFvluu`jiU`)Dxc>%?zxe?R8F9pfm=`0# z9sjzG)7r;LH0H}J$d4VMLF>jih1QqA_I5Ne`4dYIw2IT5gDG@^PdItIcL5|{HRk=P z`UcjoUy;rB9W-d73C6IQ)Lzzej94pzc^ku&<9bX5fGU45_bnLq?0}@ zK+*8~*pn89?To#}kGMvved@?HL*`C%3ZTbso<#TU-xZ1?J8`A@2fTLZ3$*kGkna+& zaK_{#V8(R^d@#V-vXPy^>%!u9|2nOZ)*V38a!0{qY7Ovv8!#h@K)G2h$qEX?_=a+H ze>sF1tOK4T%Y!9@r}16OYgn=I0~t#IuVo!@qXMl}JBG zw5R9c!kH|iEN)6&?)q^&{GxbL-;ct%Fb_Nx-i>nxjdav3z5ARVT!f$#`?q9-f5bCv+eu;bmwmPTptFi%aoQIFzi9 zqk|5(Ah#DKmhv#IL<}-VeSF#W)LiD2T#i|{3JAh(|2$nbLBSPSIM7vCuTan zo9qvI?FH!dq?i;4pQby?_X63S&GVmBf>%%e2co*W;PRf87?6;Mb~k3BdR+qRFbu%* zqR()-j?&dF4v>802R41<;vr>OxN@~0+8Rq3laUL$hQj<^%L4FVVkvCj6pPcFioyPl zE=0tgL$R0+Jk0n)n}>wCVM%S&=uamc`?Zggmhb{j1gXNR_^*qf&^^sdnZxgjvD1_AB6KAVY2ozeT&C z_julLF*#RpbVuW2*e@@U;HB8 zh33a~h;)KD${743<-VryPbU~R^mP)W%h56Zb3<@dO(|T6m3-Xc3D1T#_R*WXfL+!E(SZ*wQ%|RYhLjrz@4^&T(gTCpm$O*E_AR3 znrZ>blN?~p9B1H~`9s&u(|D=U9H#E*AlmT-kl*e~MmiiZd-_ih`5Z_W?-b@9cK*Yu zOgF_7A0J_Cpbc+pyDz=Rvg&F_3dtvS|NG~+0(*=Q^J8i;@=h1HJr;^nEb_wH-lu4l zd>>WmSqRg1Ixy#=H|^&fWiqcB>*Z3ni-G3BsYuJfBViu%I%Yn|^HW$iP2P+uw$)m?) zr$V6mI5m)Q#<_u?;r`E3{JKMq$QHkYWwTmH>%uO)d-nzJntBn|E=T~c>H=D^BNNOt zCsT**ig-l5Cf0NMAk01J22DC4$Wpn4-(W^)T$*#;A2H8}G9S7PPwJ?&3z;dN>`k?xca;xy_Jf=S191D{&e8g*%h3 z)9QP!@Dr5jue=;cOtk~QBL!5<(G(}V8iHk0u5wo23WT&f?>PsnB}mf6e(b+#OzU5N z!{_xL*d5}F&a$$waneh8y*C;5v2#v;%oCQ*IEroOH(=)#FVwtl zjoC{X`?NZbH~dVVG;VxF`=5(oPFf^FP95xe!FWLr-b2OrMB=jX6;2pC3$J*);O`Pm z)RQXWUCJA!PHS^1r^%Nbi!&$l*ysHz;)}n3hoNvo3pqSqN1vGpz*dtE>?}wo#q%QQ z$38v{JH{B3F3w=LYXIs3>L9Hq1oa}jnBUkPChTj(ftF$jR<;LD;vGCXLmHM3r-R@r ze=>CaKEz@PZh70sDZJ4P9KF9_!SY&;1?mv+OcdBG2b5zlWK!%V4J16Iiou39O@RmN)MJ>}CH}Dc=?}^*D?I zLBDWTg$3(0_c0#FOQ^VQhn6#4&@fd3mawy^(1es*=iTfTjLF$* z7{a<^OFi^?+;J7mG<(lJUnv~ioeI``I~vu9c=UlCNSi3(?#@7Py}>-(%%QmDL_Ov? zt-)P;tLa~|5YE3o3Rc!{p)PbC?AQDUU;Jm``@#x^L6)HrF-QcRq!i97n{JrSu_fDn zzrl|68=-8e2=7wtRfOtyRHZH!vyvPcd$kcA&4u_&^>ZNgZac_a3B{(iG}y6M0hA{R z!F>~XTY461qiTryuDys08hh|nX*uV{($y$hz81|t3_@_e5X3ikgWV@P z;-Yy7>;25Z$FB&a9$DdkhlRLPA9s*>e%_27G74qRO+393Ei_IQp}*`C}0 z|1DX}I)r6V@v|8pUA@oCf8hrk?@cDj_H%Jxt~dJ(t6+=P2&JONurnb7Kg?F;$Xlet z8N)=Xwq6|zo)+?Eq_IxCd>1E8zZKV5%_Os|isAN2Vg5|=0E_z5m?v3`PI=`8;)+A4 zLqlQh++b8*Qiw;L(lM^GltiBxLe-#mcw~hO_Gf;A-D4IY^yNR8_I?>oi+cuE{Wnl< z4!J|D(&eLP|_x*eKp#1(p6S!d5f zkeht@J5+4{2jvBgkxndOMb_L~!H>0sq7ZiOq4A~dG;LPeqEC6FP@caZX zJcYTcih&s3?MK4JpMa&tSDxYgQJSOE2OCdMquM5GASBq4WxaW@ez6xSh^5oE0524M z&N{tQM#0(V6&64KL)IU2#U!P*WP8RO1dYQWv_O}JC~C#;&2OegYQgYwu^v7vFM*Xt ztXmM-4{Elb;IL2-9hzhY;+1}=+_{=QpR9#7=C;&ioe=l)K_R|r(s|CM2ut#FMKwws zFu}^#zd`cYAcQqs1D&SKxnY#nNMMo16k*^pbmw=r*j3I3Mh4bj0 z&i}hQC+kZRBP=3E#K-Wza&vHq@S=N9#LxvJzi@-WRwzB_LRKDM$V+ogK;>dH?5WR! z`Y{>#c}1C+7x9zKor$<>w+lX>X%FLNH}L4<_dK7cS4r;;YbY_lfZxybb2umtri~tu z$9#fqlEWB#|1ZX`s^QI&Foo-Pjp;)PAIuSOC%X)0@p4Y*fZpbH5TZK@8}$UZJf{KZ z$bU#3Ra4N%{|gB2Qp2epD>aQ0k!VIUQ{T9}`@yP9UJ*HRs$5okD3PN!sjBv9{! zdb?9_{rYUM5T1jFj^=Z?0zEh_?-51M`sk!R!ra*2FVGYr#9tl! z7R4+U#2r^~$1`%>^tLzhHf8Zp&Px(&`=juXhBMjxuLfi%-UW@KIy56kVNP2pddf_q zvu_D=AEbSuZUyVVNeKV(Qi_0-vLo$KSjbf;%=aZvLxy5>`)@4q@UAv$vor!V zH^0S)N)>c&$!o%k@x?jIE`ZamH?+WI6|wXe!{I0{?BBhQ%&g+$-Aq^55q1@_bcMMu zciKQ~rVw9KV>w2=B3My(5h>XC~w%KF$F!o{-psn)?l@C9%C|?!TO}t5V*7zOx8P6A=V8D-5MOPmM8^_ zbBEFO&Im|uKEgX@HXZjalBUyAci`%W10-Zk3bd$wz!3E*P*7zA-YSdG^>iKJF%QoLI67d!ZZuz!O+aWad->`rZp>Xu-1x(N3>C}W((L6|)Ho>W^i7m0Zs%Roir z-uOune5DAtp%7M7ttOJU>ag8q2k>NB&ip?wj^Z*yS~@(4AJYUOPyR1RsU0F21L}}| zs~HXa1(|zA9!(gVxiDrsUNrbg^LKi|$i|zna>iO-!O3jsVLQ7e?5^>ptsGo(s<6ub z2MKmEK@xl(W=@ZR_gDUaoOTT9V)rOz%lqhak?rbCz2LRkCa@W<=e^r+$GG8-Afdp5 zUMX-z(%OyU$6~z+zK8qPa?P4azNs_Io5xU z#D%5#gmwkcN&I0rGiMN81_R)HV*$M#F&R#X7ebFrFRXhVjDM15F_!)d9`DgM=s)C3 zUw7<-m*-01mQpT8or#4si&rq!bq?nF%Yf_}FW`7I;IqO6Y`7r}f0lhmD`3oxiTZ4( zAB~nLb2wMNJHf@KL2z=^1Ist5)c@HTGHCi99OjClw$DoTOsvPmdvD{tOnzaRfR)1Q zw+(RSw<3EEe4>eYBztiu*zHwdpkTR>E? z6Q0<~I3~)S81zw`24ojtj@VY-v$RGsx>a7omJ2wMNGMk}s(PFs&BnXe^P#jXfhcR*5kg{kl1~@Q3@O4#)8J_{G zgf^gpMgxYtkbsFZYvH;_B{aX3fv-oOK)(Jp+SpV|M7vYy@ZI@1w$hvSFJDIFcCCZA znx5GHafca)cB;@)nA7qHzEur@iPC%!c|MQ6_msoY92x9%NXO;Dhk5Pif>C1HM~t#T%m9n5{g4E?M`#Jd!ZZpVke#Eyh8jVI>G3FQUG+i$K7i0Pj}^Y@W)8wU-W{ z+OgyG`1)Gx^Rgt<<~rdo>Cf=sK^cDa3xOM782e>KFGvVDq2&G^g}E}N;PL7+{$$w^ zj{{Apz%mYf^O_*_=_AO{PXxs`^&~SsE{1~b$5d-=cSwDny zfq|zGzhbT`XrKN=g-grX{XYxm?G)sjuuMgam<<;OxO8c~GbAe!u-;11TR>MLme-0#m!InNRREVZLRUO zi3#l8b_EuFug5)F11L3^4w5R2&o^%>hNRdLUTYQ}mMDO8A2;B1kA~V?Tc$9W*VOe9#6O4aQ&AIP%8;#2^@`~in z#w#>bz%lh_P&6@_PA}5K_2+d_=4@J=?ac_Zt9Amx_H^J?HGorTI=k;=!#w#ix^Gz- z7ITESuqBV~^h-qrsVLm1kpODCmtl?KE2w$kMdL1{U{q}aIzRq}>&9w#xaavNxTA3#%v4sQ%GwstPkDmrN_O(50$=fDUIkhl8ihCZ86|J<94{Y0=54{hf=vxgT zzU;fz=u2zC;^sI+SMcDpcPx7k9fZlh8}WHX1lWH(K=)Y8qlbI9!z(>I2xNE5zuYYB z(v*bNo)H{UaNM(17g zP{KJ4PbeAEnr-2vc*$G*o^b~|HrU49QLTZ8Ma&(2UWo7J@eQ&D%Td0^0(AC=VSfK{ zGI75Rbu1F%hh`arn~NVYLlaV-paaH5!<>~76&Srg2X%OIP@Y!EDV!1m#h2f*9kBp+ zgt2GM*Hytu=MhMlw1Dnw%Y|yE>+oup8>}qR1n~quB%F~#-E1Gm0JI`fy5aPw$tjqu zA;35MxscwSa)}BIo4|3YHoRE$6hwA>hb33s;jU{w2)=j1T19V|^5!8`jY`JNizaXf z-&sP$&@O+a8Im4NC%LQY$n)Euc>5=&5&2$g zn6hdFj%qezg+~U-*pq_lA74Y=hq-K48cb4>&x3NueXI+5jb4|9xc{_AaiLZ+9-Ak` zkF-}rw>`Uv^2G`)^i72q9pljO$r6uBBw^{iKcFM|8ei?{#L%DuoZ7ksHC*oV_K6f%ncG3gtwawalBgx4rei@E_jTL!^lktwfo z;X{(pzXc}REF#^q&uBn$FnO@{33gT7f=Rg>iG@}NzCBX|UF+U}o6IlLzwsF5da9uQ z;+HV-R2$xWEk$qitwdiBH=No(2g*~<0$A+<(X_)T|E(GSof?PhH4Tt8{VjHt3vk`> zBbEkjffRK?e#PchP`2I&G+6d5#QhCv_`Lwn9%#Wct_@IC5e?T&a_O^we=zVayTjY{ z;|=9J{4H(E`7XKvD|J87E8G{z#M1QT>ChO>@Bgda?M7KZb3GcJ4S`ZA9{)j>4jK60j`Z z4VC&QGQQ9UIB1^0^R|zqCNqcN()L8&@~5+LMXo=#`9+fb@BV;gZxr0zDnmb9W2FllqVJzFp1lVWcnr8$x)m}pMC4J6>@NCRb&ZOIqR$`;p8d$jV1KLUo zamBiAaPPqzXqr9|ve&+VYszoX<7O1O8)}cYwd}#vI*c4s^2MVWjS#R<1l|XDqrc}% z2$g+{+7>F{&{B#AH3^g$7Q>dr7a;D^4z53IY27qqxWm4`GXo!yX_CvKR5ptY4^dE4 zTuY{YtAj1y8t`g7k9WJU9JaS-pw!G%Dyp0h5s@45hVTTwfw?fhO{ovfZif)JbZ69_ z8UoM0`(n`&)^$0oPcu#jK-#M9FjdVB51kW1$UpwFr|IF)sweuia|#g**r zic3JzxERp-;1Acx1}x1uh>BXw_iR)LAo_uD*65%`K?He_7y_e@-4skDm@E5QI8S0u zBK|ib#7*Dm4L=<^*_@W~&s%GtP%#i*cDTdq0S}z_`!Jl+)quOXXMp=B2&F~+ap_Az zTu8JaXkH;s`mYa*WL`mz`Zg54X^XRT%rJh%F^>31J)84Z(hB!qQ1SaW@YMf--Lu!Y zC?f(Kq^!XEy(3vRP=r382QhY|6YqC~JqV7K!JDI^AhnVY5$qnn^zK^p2+u&fabfQ0 znvEE4o(YcI@8O_bE}C8he0chJymzN7aMcd*2IJiD@WrV(aV^5M`;GYcTJbJik24~7+Yq+db&fX)V@n-HqI5c9gD?Jf%Yv+yc)O)TBYnk*uIB_C|<(Uf_6xL z`iaGVhbC0Q?hoa7F4ci-{J9sV4rhZ^UjYoC>_?f^ zH(*@+GuR~Lg34+SSbpsnq`d8fXWb)o{oyz$StZP;Pj-UC=}j0US_tmMs!^+V&Bsxutw4IN_ zk>a`GW#j|}W~{|Ndj zp|JOqFZ|>=wBs=E>>^~DXR%lqRYc{TX=^D|^WcndprJL2oxFCkez5Tq_?W0WutKAw%| z3@>54kW2Sq0h>RnvwXzw^d>wz<2lRuxWQP{T)f3^L|5r{Je{-@6R83`T~BG8j|Gu0 z42CtfW)P~3Fk#sO+$j|a*FLPmZ{^Ln5t>PvtqYM1Y=O#ukzg9wK%8EL!4y*y(C;tC zib5egbL0XX(LM-huLw&X2yy9=RdhoB4|M(f4{JQiVbh)cyf-6jF;1W#MXG9W%bOU8 zUMk2};hpC+G@K)kMZ_`wLMZN;Ck3HVnXvmJhjwaN(Y*66fV0|AZmK7q`|6D93H~_5 zt0n)Q?jlDm^5H_O2PP&efplLNmSm{Ifk^^f9UVJ5K-u$4`y6Au8nCmW3))22(uPi4V`F!-{49 zaHSsOKswYy`CA_KM4$H*;;?GxU*s9@&LGIU3lOzIh z_JISF)9KYCZKR%M6mONJ@$SbQg!|zi$UToX(8nn3UF-$>gxetGcOmtT)I#Cvr(`7T z4F%;Po}BzAaAE9(vysm5CpH4Q3*wOEdx3Y`Csb{X2eSj>)b6V=377FCPrakC=upT1 z7zrduq6y9&dr77)u0|`n>9EZ2JEY6mLFS7Y=sDyDxl>hPTI_2$@ZOBnpE`wKUEYJ= zfCK(s%Gd(0C&E8_8TfIo8AHGPBG;>0m@cq_-S@WQgTLSK=6zMTm~ccv*~*{sQZpds zgCO4#>%il48D2m42aXr&k*>U9*frA0OEX=Ir%xV4*G+}IDU%yvmZm%G&ho}Da2(H` zu0rubMSMw@pjwbP$ab!TqsRF;ORyVHac!Z%y8tC-uE6!)%FsLA8@9CO&`E25aMp=i zp=V7Def7i}bT;R}#6d^gV%1F5velt`SRXAK#!XW)j-n!djNa=m*eck6Zo3#ZtQz3fKPbkkRQ=aq!Ulz^oU+m^{L_r zY*>j6RVPt$;U}=Zy_{~;c~2UfzCuL!2b`p53(~7)*msPvxdSG_`m4{OXk;GR%DTd1 ze?byFuaYi2^d6oYh2plX6xhmmHAd^0kLK3SH ztH8T&ZS?M1HixjxrXt$)c;CAo!rTP7x^>^7vhN;R)_);=-ET10EtyE$R4U}2UIFKH zoe1aFFfrVbMa^Ud_&N^i)L@bzca2$d{QN&gc$B>ZT*MQYzJ7i zS+ZO?4+7?Ug5JGD*c)yKTc+!MQz|@K#)iYaZ{6 zY4{eca(hYbrYjg6*i998SmCs%g52wer;}T26j9RLo8U+WN{`vW8kM>DXpbBSHZP{e zy8A)v!l{o@%K&maxW4V$hcFsZU_5| zR`mDL#b~Xc#W}wHHgRwhmhDuWwY_6-!N(VqaETz^$QEV2Kq&$KpNrwJdtE1Z=iDGk5+krX&6fCAgb~dU zWtgumz-?Ue4<$wzFLRX*xg^~~HZ2fDc^^~Ga6EH3rnj)p&^C-QQp0b5bs_NLZj$Oo z@xNckIB(WBk{_ExV7_Pq$=u|Eej%T+?(=KD~+ z@dWw>PQaZ9**Ky17A{yDfjx2&v~6M`Q8>cxzN$YVPUIjJv&!V{AC0Ec<9;a1GX%H1 ztzhs?9EUu1KoDc22F2~7FyWE_DHnY3rU%tkhRMR)B6vNym)yG24sF{G z64~rH?EP#9@+FN}fA9{36(!@FBl`Gbg$;iHF+y5JCd2vgG+MFX4Ti<_B1c&t8+d`} zVe}go9}?#7ov{gT>=WcG?}&!^t5tX$xm*}^Sb(#Z$Dzar8=S6Tj?gyB>zT9&_Bffs z!im;cRPRhqb>-28`SutlKOf^g&vS|`zmaDi%n6)tjSa`lkz70hNh_DoGtdO44e=25 zw2X5w>OXwwT?%+;U9&tO-p(YzQX)ijRS>wBXu`uNbNjM0S5&1MfHN;$*G&qXzzw#J4+(> zI41ezV~}PKd64Fc^U4VR+V>0R{1L~M4}0m0zDUgKk^?k;LCmf##?UjYm)n#J+J)87 z`)?~GNNM7sUN`Wc7LWP6m~V4t6s{iV=e5r3r7D*MxsN`+qj%FUL19%AsOF~Od>H}0 z%KF<7Xx75=!Xi+r5sIN-1<2m+4^W=h!kh&5*#4Jwtu{5|hjnUje1{-kNZ1)XLYHD? zv=tPFU&qZ=6PeRS71VR1vGC+9@_aZPypQf@XI~K&d-ja+&&JVE)CUq&eW2m13Lfbi zfD=1fVwY|7g8H1ZC>Y=lnYSt-?q(;ARIUTtHYwW8_S_baUeU?wp~U)SDU`Ke!F<6% z5H0wIDn03-@$n0(wn|4$$9@$L-o@tHZ+O;W14-K34CAa%w_A4u`qrmG zN{1;p=Lz$*CtKoz?00yGbw?y3Khbd?0c<(zhhF1Z@O@w_&Za$xPh)9Mp9us_EJi^u z18|Yb0iK;Z==n~8MPFv3@r^Ns&;)gi+O`>Lcq-5wq=;J$s^HaCA@0LlbueJNo_c+C zAhyxRQM{-UU4}lxrpH-OXg`@eb2ElH=4Yu!E6a9o{s6~V*Ke$(3q-DOA;r@NAcE%6 zy9cu1(6WBe8%o8c>)7w?z#0;D?g4^9E&NU~z&B}&@hblV;i+tgh@$skFT(O`X_e?G zP{y2thro7v5guQ+fP7uRnA$c@AUfRzqw3CJj03{!?XIA-L6bxuiNPm-myqlAtcRjM zA3MJvK+pL)(0MtWPWurBr(SJ@{~Frjk4o3jtbrYn`b(J0NxZ7}=@>R&g9`s2;<^3LQ|SNl!0(V0a=}5h+jX{VbInb+#zNJ z^-1dJH(o|ROBaC6?_;3)qMTRnn*rXd3z&zt1UXV0h^Jl#MA;UTsxSFG#}Y;S6Kf95 z`6@gS*GTemhbXz3=S)35^KlBzfasOyaoLM>$CrG%R8;*Su;1}i{g5BdU$jy8Y zo^9nCFjD!3GZZaR<)180wcdmCFJFaiKK;0IuLM~$X9~0#mBXXy0x-kG3C!*Ku;Xn4 z{`K|7n|re0Qf3bZ20X=Ji&6S>%@aJ-^b`eZh4@}G*V4OfUm=S$z}DzyI6Y(z)n{g* z@USBkU-?M7f28A|UuhupXdfs|0}UG{@ys%Vpyl8N)Q(Dolc&FemTWm*lOM&24zEeq{`YuzpbYnK^`d_h zj$`;gD_FhlCr{SZf^*r~okooC;rc3J;yFGW-+erW8>f%(hW0pNOr9WjzruCA%Xx?K z+0{@ax&=h`n&US^e<-gS#sS5&g}g|PKa1I`rR4PGCaM^7=3cWTx{_*Ihwp=TdKx!g{){;32eMVI0*6jc zsCmf(r>X>k+u#h85YR;V)rhMkQen4aKFU8mjc08;al=_xdece)H96nu4M|^=_FqOG z1R23;_n(xrF%1^(4Mjn@U7+%Xk6Qy6b5SOn3>;g}nH`XhW1BmH4o<+0jxRv_k}7aJ zlkrobKi$}sK(3UZgY{D!N%PUoV1H?xR5WixI!A)EwVxyx(iLg+(`poAY^bTlf#lje zLtMV1gj{yG0J0;FWc?mtzDfa?{4M(oh8G05H=;yItv>TCD6PiUECmd6Mf5Yiz?ihUa zHwKpFLH{cOuF}d-=I-r=z0R|ts$mx-JUgxseIyuO)U?8ba5HM@`5DYgN@3;AKU7t+ zkH;s=@wu*R5~Tk3Npqv z6RBiv()4{5Xk7n_Nwxbp`8&PA|7;3;WEuDWwjIJfo%I|6$Bpo1>s?sbkqxYz1m$`; zOJRIVH(uGONT;uTkH75%`TzB?ze8;o zNPYa+ePdPjG-ETi;{PnNqlNLymThR>9YY_OL$237-l5 zf(zrtXkpA8sip$l+wUma$pztW+w-tp@+a&!*g;k$r;>@1rksV#YjFnS;7mK}1LovD zdIflL;x1V54$4F*)L&`h=;*tmUD`S-TUe&B`*{sr-kOSL&kf*|m^Jb44`+VcPiXPd zou~8sDp<=}(Koy%7<~4Wc~pFeVsEdl)8 zJJ2d42b6RynWJJlIdF6tWx*#wsWTtA$DV`jvJ5)g!;bu6JiRp+fJL!IF3XN6~qQWBImmTr{*pO1p?O zq$KfNr=}Dwsb5-}ijqQmC=}US*+SX763=x$c1AWO*_jcMnf+ex(SQBXaa6bay6*G* zem|e1N&-?p(K&ZD_rm3uIM2SCB+O-V5Y{dKb)b`Ou#y9F>p3_@SQ>W)=aOGbCgA?B zYP2}$N$yN5z>%wN7?<^fBY)u^NXQ+-W%bgOcJ0P8K4Ip}Gg8`=DhA!+D%hH-3j5Aa z!)gCTDOR=kp!jFzdAZL0l>a5s-aj#$nMrP`cqm?z7je_2NPnfM9ZGHHV2<5&$s{5jOqOc+f| zrSN(;+m{;sMOVftkX`hTQ(Kk_bBwJyW>wG0Ud9AaDvg1XV*&8)!W?efqcuX2WSx@aqxl+l?lXTye33&0+ z8CLAdqTgz?QB5Hkukgpy_&6uH^uQb~cNjwN@+uHeG6l`OKT-6{MG{>QLtkHBj}d0Q zG@aMOHH)moy4R)5732gDs#Q?y$|kJr7f?Rpwh&i0euuT`C*WR&8mQ^+#^yFIZn`0b zrWegQ^K-cLnEQVq#yYE#%)gklU_Z6a{>+w6)nHPhjzv@04!B|jXPphhBS)u@_Jm)c z=rjlNrE};b0Xw`Ayoq(#1b7)c{^I-TXK0eC5BFCA>r||Dr{gQypyE;+NWNk-<%g4K zJagPiM&zKXh9&-xc?z--?s&KBD`retPR)gv;c!tsh-o3lK3ByN*J5HnGn+)loTn$= zPXkYW0XT6a2phaZapuJkxWX73i<2p2FY?AE`d`4`^9}V;G=n$BnPAiS2>hMGsP)`D zSbXIb)J3vx!hT_B$j-yYq5UWyE05yu{(x_2E4VFj;9PA}M(1%W5Rov%s2gXb6L%9dx1b-?(S}-5sPX0g=P3`EZ(nu)M`3{Xyr(k)OB8>Fe z;J%SM;HB0UNH2Sv-}P--PFdUvSO@@}rJWKVBIdgCnj^V9Ke4 zfRZFsOZ*E~-}~@s_$yLB$T$aLQS|C-ZEnTJR5($B*{T4a*O+0_X?CwQ z69ES?1H$z%gBvO(%-0zR^%*iS-FG=o%KSr$4}E~cqaTO@-y<@(aToa{@*Gy|dxPuF zm~um>y@0Ei%&5`48Q3+YpIcxy3qxj3S;-Fy+k17HS(#ygs{1c3pGuXxftVMkma1a*0m)~ zru(ezKQ;gc84E^@LP_TatUsp%!7M}1L*@*R}gBnL+@dKlKf{cEFXA{ zn@cu>-QW=@+tPufd&6<*Y(0*v>_4z%9tepHTXIA0BZ{g0hnm}xh}`WM@SFSy&YzLN zX(x|S2b24tbn6X_Y6pQo%Z>ZZWizuQds%_c+#njhP3xeSO@tw)$eMnS;#U@) z%Vr{`r@%HZ90m{i)9IeascWDEl&n_3{r67e+}Vy)8EZkXh`CJGZzKCA7C_U^_joZa z8v1(ng4?!H3_AH9ZBkC+!rcl`FKU3=G0{-Bp&U&dmx71WTM$2^19RDYbw|7`iFU=v(jdeAR>m9BDr*jZWjKiPGqyA6L^1e5(KWl1l?KkIORbI)|xJb5APzu z`?DDY<@k|mZaIARD5HL-gW&g?ZE)Pu80svNz~xB-*K`u=-+Ot`&-)&L(6nWE@~i{S z(#eGby9aP%(06k4(m4E?7mDYO4pPVOV}zZ#No&+9(C=9Vb~sv)PL|P{zo~<~j`=`# z{OiK8b#9Djb_&&V{mEm24Y+t|GW^v!2pjs+;D#)_N5*quFmwrQdPpFS`w*;jEih!9 zaabxcVUBhcW@M+p{=Lq4Ty+8F{hiFRYVN4N=rWp#Y@i|au8{Dx7HOOXTwm{w|6=V( z(a{+4z*vBH?|>_fSF3=xqA$VDFBzX1N8!GXQN|`@d5@JrcscC|6iv)Q$xHsoTd#o1 zLauboBNcu$MMKt;Ml{?iNH*5~!%g#Kpsf2fbH)oO*S%!#-Rqw?9&+~~sHTK-+rXSL z2dzo=#eDL{)J=u&oL>)4km9fgOa_wN$Lo5>b~586RW0x@sdG^ zzR9N?tY`zb28OADE$cA`_@MBq8gftc47f@ig?g{In6|JA#rN8QO&04KWZVX+DWA~1 z$^iz;t#HMV6`hsy3YY79k~4oxsQr}1L|D}gyPV{(X}vjoTKyJMtF*Z~->e|h?Jb#z zK8{J#UqbOsdD0!(M%{Vmp$?9tf_^`ZnH7d*8k6t@JJWl&U&VH5L=TlcMC8nDjMF`g ze1}wNMO+}7Yic$-*Y<&%#86ril zYUkn%$$H4%-b(tm{s$}0yK%Q{{RlJFB(P3Wp72&MUz3FmehiJL35k<)I6cR9k!D{$!)Qt9g7F!oIc8trGHZ#X~iuu2y!pWX~|t9l^h%K*v0YlN3oszGe$ zB@9qqhJyl~C}KJZW;pf2)iQ5z^Lq);n)~Q_aS4olGm6vKdPAqa4SC(Z6&EGnqZ1;d z=u+0%c{l8z!%!6;Pf{bE+oSWE6X8$-sRqel z^xB7oj_n~JI)OOuZNP(}`P@eeCZO{%ozB0?gQW2XG%n&hcxv_IRy#ph@~IF7p88B4Vp527{w9COe*;E_r%?i#mR*fM#7xM>xF_t80I zSR$ENZQ%nS?Gd<;=$}|o`i<89?1pQbwV2E4D($+(2Y+_1A^IuK+`hvPD7oT-+5ygB zpI?eIo(6IK=k;Nc)=^mTWD54{RKhZ4A6%*W2KDYG6D^OqpxVX5;~R^>(x-;lym!R< z&F=W=)g7|()H|-qV;87eKZ^0GPVm)O8oPrm8FQ-~c?b2-d(Kx(TAavPP?QFRUvA)Y zD?2k8- zmb+<&Kh#Druk)53n!m6WuBAW48%;(eD$5Oy(vQ$N<0YJ^=_d!xLa0uk>j=<=do z5Pxd}IqhsWFvPfzI_dCbVl@>g-$Z_8Z9r?mD&p=Yh`u+|={*$=SZ}XnbLwG`yUit^ zHe_<73fxGiVG-)v>A|9+T*fBdjn9;YK+x0#Y(n{Y5Elf;@6^F6fdoi-3q;6!Cj5!6 zBg=G|o2qU#)mtQiAD%R$#q=`hS~3G(%827_m6bsD7Q*y_zkUh~pG}dY+ z%t}mzfLU+wzRU;Y2}~z*j612qql0ALwI?`RP?GaX`w;Zjf5nN(PhiiJ7o^Xj6&}?} zK+!+(#Gv8^qE%}G|HYZ(!Pz!2J3SHPj~oODc2xQ+aqAO;(kb3wDG4X+D7g(a3TXDvt2X(3+RJ`1_8q#(;%3rtyGM8^3S^y@wXUqSX>nY@-RHr)zG?j}O< zXg`kCDADTkx;XkY0)DAw!%6va`fELNsH`)9ze;!TwdGv!S@Z~1=IF!j(=7M&xRv#c zydc?RF>ZY43BS&L0!^nw_^oZ6_RcT_R~aB6J{JXPV6bq41kaUtUtzApj6CL;`tYK31LC-W?2dq`-W2yR!JhA*1i z;LJZ2aLqZ0jWYxB#4INe&Q@XG0)0ir4S^6jb1znobTMvU9gHj1V*aBL`huOsUQ-%5 z;`u!M_0Sc^;$1**^K%^hE>E?8co2h_aMT4^C) z{Q>&k-y4Td?SMOK)2Y~|U>sEtB$2CLf#3!g*kU!n`LraNOo%UKU5{*7`B@Fh_KZS` zgd38<@2LGi9i!MgF+{l?G%r?yxAs!{QC@(am~9D#1KqHwX$o?G&xhO0nd7j~nq$RS zA7%eNh7UHOIDFzNKG3&7VLL^}>-oqv*eAd`|C4c*v;Q^$yAinM{ek%hz42X<6i7@@ zqiZ`vsGP}WTy{VRr#7$?t?PsxYNzSpsTh6=1n$;Q1S&1lxsL4P(dw|d+G6j2_A zvWYYJ#kmD^B(|daMoMIBtwFwUKdeu$;J8cqL+g)j{40_RI~Bq)PtF=uV-g6Pzk>C{ za5Q3Uxf$nDvG%40Tu6NnSIs)1r(zE-)MRse{u`KmsvApBI6?Z`NT}G!x=Y&Yaf zB$jS+jH<_0j zlfnHfxfeSt5e|G@0l#CL$gQ=X$W&=%$m9>gBT@s<8=nIT4^M)^cLBU8$+~~B^QiPW z3$m#w5&7bel8nWc@GCQ$%=A5snLgjq#rO*TT{M8QyVxxK!W#_g1my7#Lh&^j+L7)J zTht>Uv-}JE+1v&KC(qOLw0P_o9Y@hoVT{Twq_a(b!|^}aSiC5Pv8QZt>G4M}o!d(1 zCcTC=60Y=3^heNkasoZm9FT1{!3R!)`1sf@@DpQ4t zj}pTvtVRA>n5;Mb^lCIc={duS1foTpB zldrgS7K7<$iZgKDB4S*Tjm2G&*p|h-);-aWN2$9Rh;qDIfpZ*s^OntFVZUyQI z_^?cMBQ1X*592bUuxh9d=Xbxt*aexGJA4{~^DA(E*M4~B%v@}>9(Z2yGb#N%1tmx0 zann^b@?LfZeVs9r4&1h(;)l$MZ{0a8QZoXNW>xg8l*GZsRb;dJILzKT%)PGf2a`?T zk!oH&9)6$;&1ci`4^Nf~3Wx&Qdw{!03|IcuKCazz2Qt$o1pN0-P#*tV2(XU8H)U~T zSwu5<%{;}K_J306bzG7jq8pcNXk-IAj6kVo%R9Ys!86>wJQu4lVksGYj0iU1tgYMy@ z=;W3|amHh;`ML>nPZm)X(MsISW_9n5W#f#RSkU5A!j+pUi2fx(5!=> z(^4SOEfSNSZs6`_``l%Qp3o%397nIx;DucR*e0u@y=E%TiE$>lQV^@H8|aOBm2myw zeT)y5$4Qm9aL(SXoPUc)AkE&3J4Z|i>=zc$8DCYY%d0}{5U#<8*Aht*%Wr#^y#|e^ zlX!YdBp6R#9D?{I@cUF3Haq2^{hJ^>{rDK_?((G-^VRW4n-KYtX-i7Kh0(`-N9aXg zUkHqwkC@hudUu`ZolIZgb&nI#Z!P%Tb^@PFj^(5TY{ogthtT-%5zLFK0@-nK=*?iA zk|qHjAM5Qst((MqYxWkjW0O%9&yx9NfkdcF0>i$hgJ5VkZRl;nL{G+xtouygYzTo1 z6J8)JG8@*3&4TlN!F22D+2Hl>8(Q$sBmqxsU{-Pg-tv+M-Q&(UvE2Y>ZYOZb;4vOk znS(mpmVwfv!wOAe#7odGw}88Z>ZYI=Fsn!qI)GD51%i=l*27>bxtT= z7T823=PAI5?JuGMX56g8V6xVm;8eI=C6k|mci02VVUG* zQ{ir@Cg@*X3dBVg|CL%{QT`R~qZi@$`fn^)ge*dbPw(kT^{KF1hj}ia@Gvc7J-&@t zNA4F_fYc54JS!QZNBLBE>aC4)wz6k+yaboTZGv1*89Xv>hauJnxxM8rN=q{ae%@nD zT5uAl4sL^O%ea(kb)aPG9_mv#6YN}V;qa|*csEupSMhK`yv-K$7lYKKakZVR&^_DQM<7vrZZFYS>iZ!m)U0oSz8xI*dhT zZHSpair{KuKi;-jiR9x0m{=7_Ud1?LutgQfIhWxDRm5j0tGU0wsbJTP?esJ^9O3y~ zke%lXUt+B2f_)YkWoZF6I%=3cSDj|==I8z6D}_S`;>l#8JGkl@+a>-UBIoao;GN8V zw7AL~U&+Jhf1`@-_`VnS)jQ$L;0a(`QXHwt!4Y@Hz0|6Q_Mu)-)?0zWeqV6>#3g#_ zgEN-N#*i33J2*b%59`*Az?I4MBz|<5&e<|XlQ>Z*sVs?o!>KHH6iAk~H_^sp5_BN) z6}rj_C=azPf~VhJ;pz=`a3Dk)hRg(b)ib(b+j2gr(e1~90PY%JYiXZ8N^r@Knp`VIKH9<&0D(O<4 zo+LFn0;*QGBqi4|_wT9mq~Bu+^qot>cZ#muhib{VqF5R%x4uQ=ZTq-OlMh4rjBUim zuYv6ba#7>NB&gJ`g^#=L!m*+l>Ni+IUCickXZ>9V6HA@ZZs}TViF^t(H3KnALKI$4 zN(I5$skqo79_y#L(8v9M(A;Dg13%sXnI&=T=l?6LEc!??4htxMY)k?pr%*JVJ_2?% zrf{vx8#^yl!o!JtHXE6MqmLTc{p==QTkHj|Uhbq^Dv5VOQedK?1~%6y!k9S)ZT4Kf zp|rFVb#mR&e_1KYb#jiYJ&0?J(qpI`%thJjT+xaHUtJZA8oc?4!q!{M#;sMk5zxI!P@9@K!R zLIJvMEa9pL?L*)9y|~~x%U?}t#MrBQ=}g0qoIM9jU=^njRw;MlzC=@UJV1c=ZgwEf z4{D|c+c{LLg@r;+SwX{}M$Y`c9$M4cj#IX*hAF86Qt`2`5$nPKM#l~8Y$)?V ze)VzIrO!j!Tm@T?y~jy)=^z!~m&BJ_NCtU(V8gQq;M@BVq)xK;((7$tC&NLVZ5`|Az5gzfjLI) zL^hxhd!BovqM-{46^GCkD=A9pMtVQ-1CcjafVS1GXz*|toGgD3>Bvxc?#Ir-s5>Z@ zZ;9;XDwK@t?*y;0E-ajq0gYl7csXDb{$09)q?r+} zWJ5l@o*07EEBaLYbO@~b+>OIF@A2}mIn9??fetgiK%-g)NEQE78VieuDJlHQ+Um7X z|H=vOEt92kf_BjScs&F*vf0FG@EIUPm{QjV~Fm ztoJgY&TE`1yAuq0=R+0GlJ3}7g15?NKv;eP#NPUcfpt~TcEtxqvJ8pQKQ(ysRSO>< z&!?YL)uBc|3N6hClRW(Q!1f2n@%}pxxaZD#WGZ7sM$8(G!!@95bso8N=^~5=43hoz zYPhslhL|5nhlmzoqTrQ}U$2kh#r#xQ`lE=P2%s2g-HVkctI**cV|JDA;;Jn(A}20I zLg~6fSb9%|?hpS7B^&x-`Z*~Qa8d*x<|c#IyHHRX>!$;CyU|v!0dl(B>GI4MkQ>XV ztgUny-z~0yqj$5(CGnqRp1=|AlixwKPk)qieY}}CegBgv`bPqLT3^z}-rFclGT}r@ zA)MN|9eb-bL8Qw9+$EAv9vk|w`6Qc(Y!?DQiG0u@5}+~H2E{#UVF%euhD8%_RoYcz zm*|2w%d*+o_nZ1DdSFAxQ)mwwp*Kd8h(Xv@c(YX;P14H2;oDO17Y{@Ged#!Itp$vY z6B!r%3aq^?4wCGyvGvS9j4|#+AzNAUpZ+dPbMgVje&$IYa^}1dbKz9B|3b0;I>s5$ z#_$In+$HPm@n-WR-s8MMJRIMOTRjS(RDkXE6BtA9XgTmdYNMAJi{g33U-IQg2x>UA z!;XoesWwSSrkSuDGavX*&5ZB*Ux859WKx?OOuy@hVqB*u#QZBE7U88>y>AY^HXxhi_LOzB zkNANbFkkj@e%|fHYgxamlJ=k4qWJ9CEv~dc7Cq4E1%;nSlWu1_;4Ujy(75y#7x&DE zAhqKp%JV&zKXRc-GPUq0Fah~t3*IpOjq%CNt zD=<0g1%5Sy0I$Yi;_U>4M{gq^+QcbGw}E~{E9iI60>0@h@$hvwDAsDGOGH@Da$Xng zm|~6I6BoeA_b%R7nGP4!VnO6gCG=>Xf!$I@^zi*JXfQL3BYG*0ym#YMzNuvigQl0z zLs$XUc&Xycyiw3A+`{FYW$xu4($rJf3c{8C;O3U~Bu`=#Z3Sg1pH~~^99%`3%%_1@ zQUXNnsDhhkJi)WNj)pgPfXp2=l-l?UJ9hV>-AxDNC5w@fhGbBfE1-P%>L;AO;xBA{ zXpDAW;z4(ZFFlqX0AZUS(-e`z82h@PGkA0t6byRdt1}!7R<5THzL#U__be)?yOfsy zUI+J>tNm!;3tVnrndDRBLw7<2O0djks`z%4XPvvwfl12Z9#&ZTD-Wja9mX|*;jl+z z2aaF712@06BxM)mW1frwXZ@8S{ADdfiiVHF>|K}1%@xg@s)MV!hl_ThCfSU$qE~SD z-DUi*uYZWB_%uv?vk<<2T1qhqu#^V z)m1R{#1OSQ$*25Nx?~-{UdvOZ*jY2udjNCFJ;8Xz}70c1+ z(J$sJcnLAf1#xpF($lV4IHg7f9*G*$42d>$dMAsA#iW1?7BHXJ3!DhMKSz}oh;P5 z&Gs;FaMkX5m|7Kqdig%ozT*Kd%yh>r#+8@>KR7peFEMpiD30^Asr=h-Tp^1FoRwUQ z{_#U3D)S@6sss^|`JH?0**|dH(}VRQg>d|?Jvd)621or^e7A86oVY%j&Gr7!2jc%g z!P zDZy&6$+4vKA69{wcRU(aKY}lXBDmT`i@U0&jkwnr!SX$g)MiT>hF*P#S<4UadRB@ zhglz7F5L*BS|iZZ$XHD({_vtC51;HV!ss@8C`j6d%2SJ>>Eag<=y8Diz9#hPX67|H z#?R|2vjF0-4;)|U!8OgIPfISm9~y!8)AZ@{%RjJ`*9oBikyPA3!V&$C{1{_r)LBb7 za?=3Sa)PNxN*g)W8VBF<-r(tL%%kYH0X-6rpw80QN+nOE(bf7mracl+UR=zqUsvnl zX@nVcZ|NonOba2zbqr2i`OP|CpW$5G57c#0qspxTuuX$;Ko<(rfV>^#Stom!8oVc2KhSUlYH3D>2$9L z3QZe>g=zfCwS@f|iiGRBKe%`&md>^Nf=7?-gnKrHkkR!89VKP)>-;I$q27-EpO@o9 zUMDUI`wLI=?{VL^1whm64x5ngHa!U;=0a{rhzKG`(@^S*6{X?pea+Cdu}Y_Op2A{Q}(^Z*{ccPwF9j)a-%rv#R0YH8-%E`wS*UPscRZ@3{Ty z39?vh0Pee#g8SQS)bq_@y}S_o+$ce>=yk#i<4Tw+>WD^_&tSU77Q|uZWtmY7m0^d# z`;!N@LCLnqvVSrC#T1;-IF659RKR3-8i-9QA_4;+XkwEH#`Z>Hw(nd>h|-j_@p_Z4;3OIQ*)toaWQ9cz;9Gr)D4bP{&CJr@bSw2m}BOg zaSSPcL+F~#xLDDS9PbjtU5|6YxL_Eg_n8v|)vtK^>jL_T&5c(#JR#gCUU-RhnARO0 zL<8~%>QDc|ue+KcFW4Ukohxu?nH`uKu0Xl5ZusxNT8v93+~A*DD7Jk9r1o70m&N(u z?zb6KG=xcroe6x~=)#@1dlO77bRfU7iM%6> z{b|HCYb>DF`a9H_`NE;)(pYNa0OaO5oZ0RO_Ul-m$v6$G(;`q~o;j*+;o#pLzF;pt z3feBt+?CJUAb)xcO3YgeRzdY}wn~{R^f3(;PHS+XI1V{pP_ zfa`mYUs+eU2cB(vMPv7*qRDN3Wsx>N+Le@vhMy=1$d$qy+Cby`cj3X|YV^JT7;agV zLTlX+X02O^#X3pMiN-pT&GM+-Yl`NZgYf>$Ex5FM4y2d=!_P5&n4nY7T!`PP>MvQ+ zglDmc-xg(V+TnzZH)ghWpzW`E6qa}mudXadZ95kb&aJ~GY^L)j+6VR|{e@IJ2WZmu zq%pSU=oTD>GxA(G!e8B>z4s>DA+wBl?{;``Fo<sZyGeCW5J(_CxeY94@rZhd-P|e8XmN zrL4QLbMhVB`XK_(1P#KG6D4#o?GEAGwZheNi_rhqd6*fo3s=atk_P=l+`BZ0zUi@~ zmzPDLr~Ck{_12 z^MX)a+!9r`OVC>xY4GGx1a1}V0%_e2ND1dt-gzexXE{^Y$cA(V4S&$)9y-4Ae-vS_ZdG`2jU3=)hlN z15~F@1$G`$A%)ee>D%~1m~`_kY!X-r>gx?*)x(*v)US{_?sW$^gW)cq@OqG%9}wVa)wIxM>8r6(cnq3#mg7aI zP55g;2*gZiKxOM=l=kdL+pXVGOz*Xd~%NWQ~VJ7rO)@tCB%pgCux`XiI0cg$n51T!zQ07SuER^*E zea&#-4*bQm^)~pS-5BykMaeCp5_l*55HFlh!?E9M7av>K5QgzAFUE zvzg!NE@Jr89}5OM;mK-a*uH8p9_DLD2RB(_>zt3^dl7i&g|HXLz}ql@NFPKZ~4Rf11Q2VGUEMLj)%+qsl$EVMV ztF;m!a-s+1YR}`(%y3%p=r=C6DdSF@Dgp1tlhpm~2P~0oRC;wK6=%$y#QXa16b5Il zqDi(vv@!BOd>-@;q}h2N7TEwN|6Ksu84lN%RlI{D6eX9j{yapRI znv;rU2E{n--7gv$k`3$47oytMFmhJ=5N?T-g!8u>;K$@8bfZ87Hi>+M;aWAgyRL_v zunxodY{%cT@H#eZyNZep_wnIer0Y+{fqP9p2|sO%J7>Jc&{^w-PImEuHCJ@KvIY

uwLapC`XS%VN4hI@X!$F@%yJrXzPdfsyU!_XFG{{SqMGv z+)+#Y8u*!ng1oCGRP4#XIcAfTZKK&fKurqq40_kbkS*8ekQikJ5STLtNf*aa^W_c9yljs*zO6t$IXAFsS4HU!0?O4t zjX|mNInHA_-s!cSAl}I`ZLidDb;WfUt{WjSaxGA>q8Pq!d4Q{q9!0^MTso{|kKbq8 z!pV93JfH9TU~;E3W*2<|p#llCWi$WP?|s41h-K?d0`OdcMq<-zS8xp*B%g9_VoQQ3 zCTbgCplm$m#&V(kVH2B?+=f}IW*G9)i>$AXrZesh;z3P5o=|fJ*5*c&Ev2eZ4zciu zG1yg%51?U~GikaqfnY9(QO$nPlW+|if1D?7O%mXOA3*WG5U&3`POC30M-Q{Z_(bL+ zU0AUV?=u#ku!kiMw+6yM_ES7|i-5`DT#Pxmmd4%grDoP0z- zk7rTek9~*7Ge6&!44l7y07oTDVAFRCO2t|+TAhzq!g&!+!|J?s79BlErpEdvLjC(mmk@~zD=_62xDTcOf;vBbGF0i=A%#*XafetY0%3X1HC(`cu}+ncW5$> zUzROi+;tG4#qSrPsFEzW6qh{~eQ=u22z^#^1!|IrH{ z{5e7AU!afHW~{yJf*(WN=;mU5u8OfJtX}6&&dQ6yrP(*Q4I4j`j{Z_yx77-_PB=n- zV-6|YSwxmBw#Su+{7L3BOOTAy!Hb-qXdAv4)>k%x@ZVwVD(j(@5sblEJOW9VnjxrQ z2#qSTKxF7W{a75u#cPhxV>|;@w-1xN=5K_zV#Ft%E zA;6s8cyb(`^tFP;na{*vSw22q%K8U&iX<+N1Bo%mFig=IH@R2h{=5(nI?w?Ab}{hw z{dE?mEC4k!0jhd+P|~>{KMR#YsUaUP!pt8pZ)3UY#ciOU;D^$$S^j^b2`_HkNhb;R zfpQHGH}8wWr`fhB8Ig=~?bcA55)IKy6KL(~2lUpnZ1_50ilx@Gh?;5`hFl*e1zLAu zUMLr@p1%2iA2(K<=i~h>3x%Vp9_Y#IKwioTjCJ^lkJua|d?t&JJha0G3p*IK9>w${ zFYx(zGk0I6ISAd<1WUHZTJ?Mp)XPtYYH1rX``RWHJ7|X^s7+ztT^6g^J1 z!n66+AoV5${yo)2$4kruCi)XP>*U~6s4EEx`$#cv5XTsI#>nIlIaeGAGGq7xUFq0}4|G?tt<>FIuu0nKWD3=Cg}lUEL- z(SIyoZaxR(j=BN&$P~=_D?n^RyXdy7pTPFeeGn54$4$*VycFxgoW=auTj~JX?$hbU z%siAJEKe!Z0;`>}kY8{iyuw~sR+a}}p1(n-V?%KJMKj&+oQsE9f9eV?!i}3JDMuBJ zposh`Sa*07GS5xW>j(bAlm1ZL`-+Q>f)|i`I~tcoyWr77x^Nqu&^#d!-l;agOWwaE zd=f+X_+CNgvShRn*@63OD^My?#^d8-`4f8>S23mZR21GY9)_0v zf;gq|8>BtI#yKTZOj@-S@tV$GaImn&!HtGok+BD$YST^6RPac&WCZNp5DeAx^Wktt zsnUC|XCUhIi_Xriq#Z5HOTDpzIgR?j^WZfI|EmYOl3yV$@DAROnM;G-J|`+Fa&)Ie z6+YM0z&-1WU~w2fY@Sky%{m$&r+pT7CX|zyv<%!NSc9CznJnw62{yxq_=27JcYhDj z3j=&SvO)(GlA^d57d-@_+(76^yG|84{jrE=j4kH7F`NCK!EiTMKlvM8j5osXIE)J{ z`w+O>@PJMLCLQ_3)hsJT$(Arwdy)r-OT5T1`?jC8sS1XBX5(B>1N=O?h51VDA(Fe4 z&7v>T`HCuBcgE@nx>(QIx{~$E72WW9e+#V4AHtOujc9EC2Swd)KA32z=(OggLT0&}g(aoa>NicXm0%ZCraAjt)7 z#%{w5)*;_nREB3*zD4HVe!S1l{tU^r#A3TMEO~Vmd_FiKEGdL#ec3Rj*#Tnphj77K z8N6%a3hS@rgUUV&C~-cI>Tmg#H%#h+3x+Wmm-iX?n*@{>mD_{w`jyZj`xcv5Ttw^6 z8mcTg8;4e`!wV+LR4P;&3R;HcqMad|}^N2hhF#1tk(DLF|+&lu)k&^8h}u+!Fw9x1W-ELTV^!Py_bZ z$`xXN&gA21aO(UhF5ufpMBeA(z>_}Czg5>E<-g~+da@s;zkGlT-i)*CQa;uwoxpEK z{A57l6soQh!=2IhVCzgln54lxN|9moPQ+~LA-x^X^xlFA-Cv}taT~G}0yWP33(rOv z|K`jWI_aJs^~B}>qv$;Rss8>rZa1l{7D+`VEk)e(rlp}$eH+?FX)8^%MD~ts$=)QD zbh1VmLWIc97G*4@E*F$nk{5gdO1FiF_@Jq~x*pMlnos6+|DE z61-NQ4pP=)aAnhEe9d}<7MAI_=kY=OFT55$ZPUenG8tIes{jl3f7RGkvl5pbl82qg zL{VwK0PmsXA`*9mhfhcNHHYe3N$)L7kl57<=B%eYeRU0PWe!=FM;W+SEt0cVriU2H z*5Z8g-8AF%8YrLSN$O`=a&9UcarFj2!9`9oxYcKZlAIM(Tf@FJOc7xB;F z7+rI{h#c*V!s?`@_%wy}5zeXL^Sk@;_D(a@sQyVlk|2G{GG z5O&MM+s#V2WAh;>Sf|0|%N?R^mI9i`{@Oy^vwEEWt`D_}+UUyg0~n~w?o(NkSeGKo z-5)%if%2!o+T8o3_wEgltuckA@{7@C@fEbb(T}zU;$S9}f}!WO!=#IRJmZ+DcxciY zQf#rmxe^Q-9v7n`iWIL#FUFEK{v)wR%(nnp&y4S=(uJC^a-`zxvyJETU4Z2fY) zEL4M^o$YAosRx{-m#ug}V-ddi+?V<6>MV3BkcS0Y1#n>3DQq5HMvvR>!WC}?sc@qk zh+Po}smw)SKQ;9YK&5mPHepnFZEZWFA>j+^%Q;FJt^)#F1aGoh& z!XIaqIk(hbgM6)+5M0^i06fupD9jo~=j4qfb#e;y zt`+22@3P0hlon`Q+lby(V<30P4<6kiC>eMI6>i;Qp4m@WUfhG$HGeQVieK|B%V9iN ztV%vj{>XSq`B){C$N9Th9v{By0STWk7%%RIJpZ?_x!jk!c=W>UrKMQx9Dw`xIYQBf zr(hx4g=->D;`e*aG|kEYtKaH_UHet+=MRFH?A%{`mi-T35P`Kp>UcHr6%JQl!IS^O zY2bf}RN3`TL!aD{1ic5fAP?U4rvO8Zb`67H&@V1&!>FWa=+|p7RTS&4ZgiajD(g2O* zZ=uhrNifC#JM2}PgkAgrbg#l!2rE2*?iCBkp35;fZhDp++18GH@895sfe>QdB2M1UaCT}Xyz*dCLnQg}Y?&@$rycKg@0>Q}R9Znjr!e3pXm@L?YX)hKNkD^St`eF>8 z1sQXnS7y<)mpQnReO^;z#;{20E4jmJ`LRWh}U%N$?tu`}Nn8>G8n?1~-K-D*Q)?Hk}$#t&4v6(my&@-@vF?BXaxtGZ6Trg(YEMVZX>tuDbsqmWV8;3y+$>f@TL&+omvRm|Ik9~6G#}hs?T_)VYeD~ECY)1p1iN6iTUD`vYKuDD zE6oRo7Z!pd9e^U~+bHa!2gkd0Fmlo>6uaXLCT!le=xPI48O;TkIn{JiTQ>wY1mLV> zEqt}(GTbP(#0`3SAgt(2I{5c+A3om+erXQ4czp(D<-37vask$AFjvOUYSd->`8nJB zA@E)V{94(7O;OUAwS#fzmajuIky?-v8G*{dM~v^n$5W1xfQ0TA@^9*57<)6FLk*O0 zxMDX-v%S8mbS9N*FvXRjJQzJ?f?L_%{?XWcoW*hnp{hkNV9LiEK7JeQQhwpK=hEbt z_c$n(h2qG9Lu5moGu^qUn5*E_52DEn@$Z%ln7j|+`HePASu-6@zAeT$xWU~eatA+7 zX@lqyLFAuVK|<6!VAb3x9PSLqy)(xlPhFR4w$34{$(eB6;s!?ce1l%;li+;10SDd| zfpF4&#~3E?r2~uNt6gCB<1gGSFFV3SD~U1?cu#iTWVr$KJb zcWw&bT-2<4MBmpW;F_~BkRaj&js?+>ZV(Ln?hT@B83!buh(Y|n5xgUB$c^YLK(XL| zxaI8sy_0ou2|r$E%_6rYZ2f6@{pmN_fFDA4X62a&J%A5J$O# zIFsv$amK$*80W{g z)&$?>1f%EmYmDdShUYAsVT;>L=xv{+k>P!t%$4e(ZU0&^w9AkwNPrCHWn#-aNw6xM zg#(O5=xy5zZgu70t38B{ouT-kSb#k3)FIc@E5V-4=j4A|lE3b?ctFJy8;tZ(ZY5>+ zh)|A7`fsYC8qVo`%!B+RKEzaRF1*>y&s**tkE&_|P{vsgJv)BDA~%+MJD!cHx>@+7 z?-D-oSc$H;%z>*hgk1STe6zCxTBL)JU%3K<6)&-#oD;OaK0%WToM3N|2wc3@4)+c% zfI1f`7>TnWO20h8Sm7BaFYl!{kKBdE$&rlv8%u4zkH9_?JzT%(7UP(`#{ckvwbl(AdaAF(m85Kez)tULNb{ERo&7kE64RJI7Gmr{+3W^eprM+&Ln}4d3 zTuk^vn#4On<4QG}yjzHGpZ3yw54&JcCIssJjX+@V8%7KxHbtH47tH=J(QzII_yz117aU!X-{OG1Na1n_d;d@zi}NB@zc42eWAF z;C-w%Pk5obZS;s@+|af*J%)!}O$73pAgphh-O@;Me7gVA72uP@hsjwx-3vlSDIYYW{?8 zFIwTvf5P}Dc|VTbumU3^HE1+H1XA_iklXbQmwNo<+^}LS{cuP1tyRac?x`nu@2iB@ zP5dykpc5UJX5!8bZ)w{iKX?`Q4!7*D1S-tO+dI}y|2tUEa@x^wqf-gy#oEKA_Y=@> zw*gFlmeQV*R~Ytw8p-*~K|l9uaQW2?PQLYI%X@PO70d&dS^dx(CCIyKCPL)b%>+K7 z*LX)rkoWQeMVF5OIC4~%&Ttrq9Sd8*?9>3N4-J55)=!XA>IA7Hb$C=jNb|YX0xUBV z;EZgI!Usc@pnR+Ys}(bdip^`_b36d!uECty9`j&H0O0HR1$fkZDK7Z-4P>2J-s+YB zkH&6-TS}2cNQJQwd!$-j7kH&Ny+djuyoF zpq*$oowS%S?fV6Z#-(lyyUW-K9-SmnKQc3A^%IPmvXLwv@`d=lr65$i7_z!!;CQPy zS170jqG#;_;YJ@6+f@kDbT6arwc^ZeXNH;Ycmk#zH~_Pftx@P2AHDyTPt$e34m`UM zz|L(~!T8)Sw4%~vdEi~B??KuXDySJ}wG||j?~#zl&ft^EvS0eq)L!Np>K--#>9HX^ z@zw=uCerBh;8Zeq`bH`{z8;O2=b%-;9L{ym0Wa2Z4F7%>?1Yn8mhKn+4Ov5vEvrMN zb(vtqKLY0ihUr}uXPWfj1m4m1CC%^taK#H%QFql-V9ZEvIG-_9oL>W6ZN^@fz6FU3 zCs1xgfG1~JiXq~gs6}!i75VE&R-Acw4KMCLgW9@+ZO~ezo8N~Rs=$n@^;X_RHG59 zzl^xuj)RxK+)!nu9++O3L(J;@$)AMR@YKi+Yu34Ab6X+Aw=C!Se)qt)w=8JB?IF@D zT>u+iKgF({-#F&1Q>b8b01kF-1*Z$_>{(lc?m>@n(ApDZUIs$xgJ3Lw)(?(vr{g4t z0$TCT4sNq9^BEg;lsMf7zrA0f^qOVV=Kd&5)enMS8G~SG5r;eYLa{3lF-~L_+?mk| z0oE~)!m)w=>*F{)(2d&5CehBhRYY&(Hj4OK(5?2#cmbQ}uzeYN_IF^1A$z|(MC?zS zpnY4`;&0VYD58F!b>gg0mF@{Hc!KAE52~f{B%LHTkKx$zLDkG-a@%b7+60lfyB;Hu$QmLDdYR` z^ZO4lOF9QFs5U;jb`F0{+ri$K+HiL1GwkzoLABXzhAET^+ZvrX3W|C}Tshj6Y}r6iq~ zUxJ-62GB092*(OWarw+oT%86fVzHhJO2x<7|Jqu-m@NcbwREt0(JM?hdIR`d4;H`l z!SPTt>b>a!@hF)G^GZhH&Ae_<-M0#U6qi#szaeP7Gz-0#%xfO3g~aHKXI z4wQZbjaPQKt6>;}rfO0Jb~Z2;_CmKge{ewa9sGXe4SE^&7*X*Ez8;E3k>O;}8{bNJ z!sVn)wF3+3RTvEp!v6%Es08DF;=mC0w||EBNqXQ|`3CqOci|W23~xUOXlO>2>|(j0p!EleyqLEJi?)}a3#+U28vo}^tKa_8^4-!gR!bi zwuW)Y-VAjE=U*UdUPP{il1{}UeR)r?%WLr%D%xL=WEDW`P2t-Y3f@_;9;Cv!N%Av`YHJU+!a; z;fH_Sg4e;HgY*c~{14;Bc|`94=mon-4gkE&KkcJz;%d zeGaN+d4sTw8u*9Q;fH{Ni6p zKB(y7E*gT5{?>3!Tx02$QA^l;(haO^BRO3)UbtT%jo92wMdjT`VNuW`IP&c$2n+Iv zk1P-45B<Pnp=sFC zuYzjT5-@R49a9>DL832-GqYnCC*YX@=(D?to{ToO&XmIY6LTT_`5QD3-9cjiE8=)M zD3c|nrtofi68un^2{x|1c^N40tCuz=4qaS>$QF31sl*K(o+16U3P@so*1XSSKc2|ructmQyT4S?%9M>mR z2k5DGFkY7oVfM-}dH53=CH{oCBQ2Dsu}=MpS1^fNg_V~*u$1Lu1-4vZeu)S**>$#< zHoBj-vMxrys5?xW^BDG>I0{jzN@VufDcHM42=xQ}u;PU;@_%y!G+@5XQ~uPinRTYO zje+iH8w}2~A)D)7K=$MxxZu@fTp=zC#Zjy9hXR7_s$BR{eG=}&Q#5Wa!N#O7czJ0e zr0KPSMD050(1^+GJ*0$%%e_HSH;*2%`30}{ucTT#4nXIRaCq==9z3<=(+t!BTwGAc zX*R3IVJ~+wqPP#O+(t4-o*#qN=O;JbcJ` zKz=8bU1ZE!X?K!1qlxkkoyRauL8urC;yC!^a1jV(l87i?v*@o=5n5j|sWZ zmrkX|&v483OaqhHZs__xpU4COEP-e=$ZdcPiZ*!VQ6z4;A;7cVR0qM+B2j0x1Z>M} z$MZi-(Rh3l%o9mLi)FD~KQ6&T@)hu(ZZuiF_z=2eq~pYH7d-z|7L>fk(DURB+&L!@ zPx@9v=g)=k<@RH&D}9D4MK*X!H4pXATnC%`iNIldBtZin#EfxB`R#b_S%-PheVB23 z)+fQOTR|B3wh!+bx6(I34$yOY9hTZC;o8t8RQElA9NQapSR~?m$trNY!+fGT!?1JY z6nR}82@{&1s8Gjk27$-#|MM!8H=TNExB|o7_Bn|c-K6Q za3Hb~-cG5EjAyfYJ*N>6Rv*XyOU#+^ zFde@;dr(7@*I;`wlJ50=PX;tQ;K+dxR9nj2*o|GgCg-{)0y<~?!pLr{Z8-m}8g%(pnM8xKZ{j)CXi5t`c5 zkDJLjH96q}4x<A;dt%Sdr!A(wmnCWI+U;d|RQ#8o!7J;g)r?*?!LpHtpUIPj@i}M|uJF zLM@&i$e~mAZy*|u^RcINmyvo4u(JzcY@&i@G3*mwr!S?-` zc+`CySI^5t<{Lxbo_G}0e-5(Sn1e383VXABxOMoFJe@rc_E}YdS!D0-ZmO1H}-J%n68Ir4H1YGEXPJU zUs&s42eVxL)y<}NND9 z^^dDDVa@ffRwYep4zRzd4HsNEM|a#Q(D01|>bRqU+oR=!MeenkQ@pN$;<|9yDc+81 zLdlpMlgbHsm5nNUEzo9B0qUuphl?{WQHPX0u($s*-58LErgoy4>hASy-*^Q@qo#8H zonYcw~U&Lj^mElY%IAMii(U|Xtfq$7Gp4K z36I0pAS+DIH-L(jELVPSNPUIEHqtZe5JY`w!@1*eoOx$I!LJQ3@$%FJ7+X4nNG|DO zPN`8;cFe}JM@sPf%##}8dH%R?>njwVc>o(PWP;^(9dcBnfpQFMP^#4)ql`k(X0#YY zZl&Y#lgtfj^#h;Ej-%^(=H)hOA+X&Z%iuJdThyWcq2)wev4GOE7>X6g4zS=&~EYv6}9*^56B#ZVn61gKP`f} zD)o$SHv{h*N8yB7@%TF{I2_f00oSJEb`BjZ5vk7{`1@6spf0UvVKce#|(1?dPeYMXd5Qo(1q>?{q#3^L7o3}a1`|7 z>7IQ8SgUJ+O~GzhR=|h0SGWfkB=040yESVPO*aALb_FW!5~&b(1hpykyE#&Yj*!>}CrG2umOlZ}{D zt{r#j=mGzKUFdk@0xBx^K=oJxIIMQV-NDmfyV^;pQ1F5q+N^hWp%eCLIpLYQAFy_t zCw($=09I|=iKgP+xZ0xu1lP_W`-YuR=59UA(EW-r$5)dhR#Wkmpaq9NSQW#L4`--e zDTBjFXYl-=YM3mhix_p0@(FO#e%)kFs9%hez;X zQyNIjV7;BC%u7FaH5#%Vn4(?@UE2B@uNgn08F?q+l-OU0w)_YcbId{Uxf6WVs;A!r zCP4N~2aFRrymd7hMB-BM@aaBodE7C!8_tLP)zmEkqjm#yjWh7~nLN&sS`TQd@}_=G zG1RrJ1Im|sVNSj|Ec>Mne~o?M^uj!PHwj=Mcs7dVj&W8zQ-e}Iex7^?7l(GHLq$X| z^s{`=m$dJk)+N;Gcxnb_H#l&w?p6XL(etQZ;-ca4_XjnNa>|sAREA~x!kj@# z2{`HPiY~XJ*jZvVhTdnr;G1$7Ssn;S`R$>ER>0FWR`^|OD?E9+6y$W8G05B^5Vhy^o$+Jolgg%MA`f zpyWEp_3sBkITv{FwiaeDs@FJYX93dL4VY`}#FZBagCoywu-`iok{aL9OVhhSp>r56 zm`#Ry89U}SapF!mzQRdULdeVlFQm^HbGzX?7<8ty`-C?rO|gRJ^S|Jf%vYSR+>fWO z|AIhdJ=m&VvXGab+)S^+J7;+qVFe7|2>TO>_zNVLCq_=xR%CnJ1HfI{XI?7lJ`q7#_oHKc<|-KvBuqrve1GeEY|572m1g^NaP$vxg}4EOKD zY0aHDV#4@%4T74ny%X?k`*-GfypEUhA41^N6LikXV#eN0hdG|-;lcG+q$S6bPO?{n z&z5E|(*6%)j(#E=+brp;|E_0Ds;j~&y?G=lDjf$jBsu;Y=3y??=E|^KL{yqr#-X@s z{2ad*BvcL1@5fwhiCRMM|6K_-Q@YZ7xeNv-_rW;y1KoGI2_~M0;aY?5 z%nkbiZcp5P z(Fo4sclh1m43fnhI9~Y`RZU_bD&sqLe1C;$@6*VXtx2$D;3UMZv?BX8+4E1n1K((d z!1uUx*mJ8C(qB#BxJ(9w9A$etBLU5)4#{M}+^5u{hvfkuOovaNEO%>K!uhjeI{sA5 z$AHv98t6L*BIowNMPVM^{Zj zZ14_rJloHaPLIHcALFQKZV+?1`=aLcM98(>fb&w9qR`56&T79d2;H;SP0D;1JOXB^%G`gw zj1!fcNQ%@xK;BYuyrdKl_g<%>#{MBxJL-pRL9UE@5{HJ5o}uuXSUh_?lq~Jpjr{?Y zpi>tK$E=q^@v%y*u84rfo3+Tj`W@E4WIaFMbn@$ECB%A5!&1Q-)|y=bfp_oW6`50+ zau09e^~s7@^iPGkX}wAHU^7U*7=?A-e=#_r9FF8ILo@3PczEp@@I=0ml;??<&?V3Q zkGsG>Q<QIN;wNA`^6)4ZSc zf{c9aMT6_bSgDtXFDqOzh4st72&4drS)x|dD7-Xb#7)7MIJs*DDZW1erL5CXF?v*E z@^^Fe>g=L>FP=i?gQHjYA3{))HW=4VCe@cR(Jbl$o=b8=ncH{qil`ujWr#ukumvWc zdItv2uF|E9;kH<@82i?(1{Jd>5S1suyK#h7g9Ulc3GX6b7fTdsWmL7;O8*$;>ms zkW<@Po@^3L7j=a@?ZcRH&>e!xkUXE)M3>dBff>ntaDBZC9+(j1S?xWH?}bl-%B;Vz ztI8BD_YMO)Nf34_CN>$t*y!gE39DYCm8&rBc$h@rUmKsaqQ@;r8o zGyb*bXPkDdnK-5h^4|S@52IRr7=8aH?q7Kh?J^!gk*gW87b(M_kO+*H+5*d3RzR60 z>#{PAZI|s+3=D3DYhu^wvTJKm;nQvKVQh@+Q43(R_#yik+l@U5D$Ohf5BjnufM2L2@!l{SfL&6g~#`6I$c_G*7H7tA&xETy(m=f$W2F)ZW!kTt7^pd^$T1 z&qk6dR8>Ixrpl@(KPJVcV8U<>B)$tMF zKU{^Smp0K;EF0fso`SJ6-eBhE9;|zA2VRzg^v@cK8M_2DyDxvm$ri65Qv=DXPzUh2 z{s;|2qv3eqC9nus1ktayu(M34yv;}Xs{)_$Jb%9_;-@~qKU4#>4ljm8GmBpJi2=b zYF0lP!iKySd~R-@Y5Ri@h4X@-WYaqc+^UNF+b1ZGH!Jh&{O$NNbOg7w{DEjA_T4+0 z4~~r2JI>cZ7q8BO(Cj*#KC_Ze&X|YS&uK%U#ys+Rc^GQ@3FDnRh4k&^Jec}(fGhOS z49;Bq3uyzRaNg4oyArrm@5m-}t!FuH)@>bCyn%COIfApaKHfb37kS?9M0LL+l*q|* z?ppSd0^4dFFFk-NE}eAay)+1UeVkj8umv)wMv&6Mi!k@P3Ldzwi;{DWqFF~3$V#y@ z%d8msC`1R`Tlb^DN7k=TN+f|@8Jxl{NfaOc0oqFrQ_*$D;Bj3r-qb2)9mz&IQOL(@ zN*E%)u7pDDB|`{2okIU>TESgiT|%6Lqrh=ogbtR@hu*#3aIE_i#68@HvIn2gD}8*t z7`Jz@v#=B|TxPC;*@g< zn}Gb2#940a1kO6CftF$S@VCn&IHK->>xPHn_wsTq`}G@rVwXV5&Mx%Xa1TXpXVdc4 zhjB)G9B!YQ4(^c-#Oh2i=-V6vd6rXt?AHSCbfV!7M$>|uo!C()fh&uqlW$FxAbYry ztcn;XL-G35I`su8?rtZbod{FinoJxu`oUvP1X`URgz<1~ zG}@C3!T~y{`MMrAKmUx|1=-J(OT!6~7jP=V0}ii9rRU>6kry32vg(fmd|f<%M->>$ z)U=IGRQTY3|0$5*t8wtlj$gB1B>?n|Qc-106Dv6bXgt}BCK+$Qv3X9g%WD!=6A!w% z+YpnR%%R1WG0sBYaW>dC!h8J!Dl*2;+j{RFB)sr|PD>R`lFvW^(}QqqJr@n0Oye5W zb-_EKUQ(5R7N*zkM6C}q(Ac7tKB?Xce`l6rp{OLhYiOa8iq~=8oYkD0dmh2JXJMe@ zI|Skz5;&WzU!bN3Kkx9(IG8;9J zHO~jh3Tu!qDZ|~JU!ZT+0DYSB3f^X$5wUP;;94B=FyO ziPZW%`@(QC^nP<{mDjDl@kY!Ud`}C*b)D^X+Uv=GftCeME;cz*v|GiXy5pP zZciptAMV)1Li6(G|B*f95y_B>L07>|YqEJRby|>o~z-`uG`( z@y^+Akf}6>Z1(7a#_1m*S@|l=nmz;{XEOKNoM~_yhoD?<5a8i_x;der&gw}4-gg%& z5t0u>reBEU;R(|G;50Vk}G+MNJ(u$gKT>Cj4Ry77X;S$~n=izTWO7*TOUzch^3IFwrS2yIVnB!dTe+Eg$dFG%ief>%q~u8%9j-Qye}K z%Q{>i=%0{COxmCd)2F1MtY|dmc_(06<`^6^_XOEwNA#%0l7J53<#;%w8K;HJME zt3_YM7MRWWOUaopVe`Nxcu!R@P9_e&?|qNDbO}Tr@`6P-O3}psIZofr!KKV4^7G;} z7+-XhbKNfq49AY551V!GF!=xj$H%}!MGSxXuOT%dLhQLGz>{{~%`y8UNq6+|(>IfS zaqHbDu#7Q&zW9s6Xz>sY@9xK2cB9a)ug5j<_yF~_vBdl8OSJXt2OY`t(0AcCPFl-@ z_VNUA{7s1Bvp91|0vqiTP9P!DD9-;P`BM zPqYGftH0o%7+dUb?F2I~#@(RFY?ovJQ@2XMroDH$>sHF5#cBfI`-|ADDjh8N;$YIp z)5Jnn14foAbFLK#@SZ5B{hxWGF=kvtZfog6>S|ZK=#o!g3w?rVbC$!(V+o*c<47da z++lnES9o2p3Zq}ngeJKl(&Bs{-%mKemmDsd`4zx|%t82iG#k~l_TUfY0NAzdn?}~| zUuZAaiMiV~K%@mVw`GWeVUZ&iX*I&@p=|E)sv2-rO+@X*TGTp>GTj9~ z&Kv8dT5@Jof%)RvyuOj-8M(OPAv-PB-^CO+CC<)=?KodQ3dGb$SYPxH1g6&FzaQU8 zwNwNh+1>=rnz3jiDx_((<=?KT6MmRwo_>*a|LNg}yg2x8-Ao%X6* zqUbX|-u91tn){u8prt?@^X~GKBeRuouzejKS;NPha2KQ1jRtf}x-=%eU{3nc+2}Xb zmO5|9!?g#5KqtAD8p~(mznCb@-Lo3(FP?|%mK6~1pg{aW99dt92WxLlP~~kUL{i5W zs%Bn;gIa4ji}ybwGZuN%OIBaOWl}PkyJLvT@UC;M_AEu)wy)%H(p79Q^u!w%AK}q? zZA6g6p5xU=amMfzj5D4^sb@ZlsC}V5eJjC5=L-nb{Y8biP^xmS2{bEn;rCu!EKdGR zg^ZrV8}A5M>oOUaYk~SAiXt4Gq5y*JtgCGI5!MB0;VFmND78uw9lo6ba@>*ZIrIdD7r5Yb2T|5}eFx&| zAJ8OjF5A7ufq<0{EFN#Ado5gXrfNCJRNcjakB*>r&l?+yHh^xA166t41J`+upgL4d zf9&zWR!zoAVtJTNmL+g;s|Q?s`xw3ERAK(lk1+MdAgbq^V%h4?@TRQ`ou=2}k~~)^ z6B0&&p|4~hez>P#1WR;AV9{EB<`5`=wqMt|!)x|aq>n)_tr7*lHDLQ19z5N& zgB-1B0G)G^P%txSw-E)P7tZQR+-US+({8)zd zDewim)4B6U;o5Hxh*&v{*N-gWG@Nfk+WQttjGf5MkIWaH^9QUFz2QJuCf-#N(%jqj z3i_QU@a7&tUVn@vv~?VXv8q-qEpMk1hr&3DVS;pGzc;9b>%-=;CD>Gc1z!F65B1J{ zL(xnBaQjI?I9Kn&m?*PRQ1>45IlYGAQ7x{_?FHDOkq`Ax-oPooDl)KhIq<7R5cx^t zR7+M67c7XNS=M}-_B+ENeDEP2Dt&|XzOx`wj*!{O;#hgYnzSe#fGHPR@k5mp>ihq| zCFOy1w`4l5_`Modof)QcI5$8s{tx8DZ^Gp)tGM^lb~G`XhaZ!|$q&lMlhlsHjYm%5 zntk(NhS&?}Ig{<5yCd-f~%1|s+dC1+> zzJzRYjOI?hXARov>^W-q98AR{=)GE5qhn=>>Y4GL)$(0bzu$1X+<5bR|^46{~R=z=%SCkPNMFd03xdX2X%MkW(IBR zz&Y!-p+UkeI=-_A_0Gg{{nw>~JXcWjdh{e*SLR8*Pu0Mt&5lHMz5#4fS_BQsf9TL0 zBicGNpB$>OfsLEz;cVSPbcz`QC5ihu`;3l;)l6r6#}&}5`B{f!IsZYts681IKY=|pg4?ccB1BZE^fj`CvLM9!Bdu^_q|L3t^9{!J0Z!!-Ktzdho zqhDaxdRv_HYzb;x^Yfld=R>LV0KOM8hK@2jT)n9PmgwEZz^`vP+w$Y!j3Z-k&wPvP zvI}4^Q4YSb8EI2Y8EW;c0I?0faVysc*A{-o+~FHk#Jr95FV#TrWeG-=2x|IV>ILJN z4Ez=S2WqO`fp38`&5vmVLA_6~mF+lOHu}QC%5uhtW9|rNJ_t2xf-K9cnLRU8P~g$#DuRgB7vix!^FYIsUsI}d44$~e z<838-;Al_fj>|_fZmT)A{ip!JS#@;%uOOKIvjqQmhk>?04o3Ver^jX#q3>unts8rZ z87IEMfO-~|oYv3$5B5S?s|6n1>4vlKZa|URRM;+83O`dS@RhbIhCF#hx(%OE_sOa- zkWvL(b@f2-{(Ag0#S~Vv*`4vFN_@Pa8($njaQV`Nnuf(7J##lr3VKb}DodigcoLfD z&%sx`%Rry)flnguFxrFQ8d27H-t-#lZ&VY5EGayCFp*Ppxdjux7Q?ju#~}Bq50~x> z05!D^#t8lnGm2cm?@})b>zxiu2|qcc^9#rRaLG;2Rq$`gXZR#sKtrY)V#57yd_P)A zwl|BwHmz`w|L6w)L_-K!aFTNFFCwOAZ^O7w6v`YIfzGN1YTBKTo`TYt*(ad6^z~V) z@o)+)4Sqs(E7L$XsSpiiUeb@t8zI0yp485BLEW6F|Ic_S&q5v~s%OFc7r_v1kd0bD zeK2&m=dZwAlY01&>d0*tPed7&E}ZW^0#TJ3 z*tX4(T)ppxdP&bY<56Phbu|hXExt^?PvU})_EnG)wuP?_y^M+e0anB_#?ZfixQ=Dj zM+&n!>-L3Vsf3WGk@s9UDm)Kg1`lIO?J&&OVf>0SKgiO#Hh9_Dmt`>m0e<;#!WVwP zI4uQYV&f0m>O1h)NV^=Ta>Li&Ol^7dsCG^^&|(Vh(WljV;SpDu8_F3y1hKYre-mSOt5$qO{c zw}bH{17feX5Kh!c0KcF)>^(07$;DzATO@?zJWmwc$mU`$ZVvE=GJ4OW+}$G>%iziCsKX*F$y~W=GIj0ritdGu#)BbRto3Q^T~X?^Qr=x zFCB%^=g}Hi`H1n;JC5MoRMsE!%7h}ZLY(_Lh_Z zMB$OpOR!MUh>SE`CN`DBaO~)B#*{rqlHM@3jQ<{TovVYH84;)!%RS*@7F*5EAX=QVf5<>wp z`ur>X680DFMH$iIP%TU@MJO|q=geZfL_??Dsv|MdC&c(Jw;SXn-v1~u--g&R*J{li%#RU<)J*0rp>5+qyU7M2ax9zMc96aIXip0AX8{A zJaH?>k2C?EEjtPx3ud5OJf)pA&hZZ~?8EBy0k~IM1DE{l!cqg4JFa+5Qrs@$OMx}$ zTjR+T82xlfULc5gt= zL>JD9A4a*=w#4|CCoYjc4n5Pez`}hWG`{|T(ye23y3}t_3QUH}9eQ~8*m0sE-w185 zYhlS#2O8ho`FDz8;tAXAOb?ccqdcq$G*q z`MKYLzkdQIewM(~ll<^%>KME_{uzE+K8@GZy~w6HTWM5w9eEs6L(Df0gRjd!ik+oU zniGnnjZ4Xv4tBmgI|BB}k#x@OZ#cy%7{1$hphKuW+&4Qz1Q+z;EoTk3fAHo!lwAZj z_XJ_f<&C6$NemuIXk=a*H!O)|-q*vK=wdfQ&m{0@rS13bD%X$-GduMa5M68FB zqejrb;wpJ6^bLEH_!5qq)nac9+j*`(4x5j(z~uy2s80-FsUl8?qi=>1rwL`KR2ZR2dt3l!gb08 zaJAWl%sSgh_uLYsw=dVhx1;-s`4<-umr7>tkcG7O=0OzqKZ;L=3~^S;BQUH8gf%5m zBtq&9=Z2RJcr?4i@^c??oUvPX_N&43=v725_c2(WsYcBsN$BJ5iTB;UR!dP&LHZ_3`9Y&B64=LpW4)4o+6@B`D+%Hp#!B zW>N(tEAK@k_zSOYw9y4MX>k5@D(6PYBP`$lmoY~cU}i`wZojNUBo{{W6z@f2#IjA~ zYhyjm52~PE@`0SyI*rg0%nws+9I4&OEikZA9^w|>A*Zh%#ec)|KlVe1V~SamCq z{))WInY#QXc&>j9_Dg$l>>_g$eJLVc(P9v}^ADI832-_58(~z4A2s8PQNFMOJZp5x zx~xQw{q>V@vcirEm9BuDn{;FwW`4m_tNpR|i7BbG4giI^4mdl|4Ov8wTwe6{Ud1o=@`7IHxKfN41IjC3mlq)v1TF~&7F7S zQqgO0A}JMKobBRt{C2~|lb!IQ$yeCYR)!Panm{`#%ymygQ9DzZU$c!0$T8PRX9z6s ze*>v+1QNv4+`!uMJ-k)02ko-YV93`!(*TAjQLRf0S|TRc|# zlB0d}AnVWmf}4RY@Wl+_Vpt)<+Ap#xWhTIv%DAG1rI=Avj`~CjR-M%4ow~#Ps6i}C zvzMQnuG594`}paDqYvqndEaT{PzMEwbyTa{U5a=UrPtR_qD67F3FD?7qDvoJYJFi$>)2BKRsp z$=c2oyc#hApO^o|zyDYk_f9@+NkKTj${QA4%;1$thSLwp)|j+Q9UP8Mkn}rbdssVPtYK4)o zQb=7i2P-bI+~YehFlXGIs62n%7{yq{r^-=zdrSf`~a7k$B3wrI%VL0aD2uqloQO4*x84xjnqnD;*bha3N zkyuLOvMh12-w#-M{UGP?LLQwmSqhu=Uc>11L*x{wRt4#b* zc84ea-1-|OrQN``)($?;>jX9D64|3_#%T1omlyqd1Zp%G(>{gmC#L^I^XALUsc?d3 z|JI{J=Cg>mq$SK?cbh9 zf!83sx(=2I^rQ2|IrwwTnq;pO;08|ris26rp~T!gHXAddn)B|1+tO5=WIh=dP3nNI zk{qJEKnFF~xzX{H4w%Kx2W#>JD6sp^b<0f9Yhn9bDVCWLUqKI_UC3Cb3A{q_K$L8K z2dT~0nAz=sA{9?C;JFjgT^ItQ0gbpms)#JJdH@RJimZa&(sTRk?6d-(ZH%YnX4Tm6|X-5-%V=C(M8cz4CqU*&D`uIgVUU_5r4Ue8hO?$ zd%Fc62^GR`2?1`>!){R2mcSPq+&HUmHsMueew>*z4JLhH%mSoOx1nh z8$FqPj@Sj~hm!I3xhZs)f+>nB1oKM&#bHHzmFx+vFk5GnsGeh@a z&OKQ;@k9nrZQg_}FDe2( zP={~E$oVj^2zS&wQB|!c7%s&;R6pZD{c#Nhrkmjghf^qZs1A?lC=$IX*NJ178zv5V zYxf#AZp(Q9p@f_f~jud=xx}_M zEHQ_-E2j%4Us)JiljcZu#XsQ`GZ~UDR72c{FT>)gVW8Oj8GJSOfq`-y-jE)E<*PoU zs*5I`)6^loQD#tKk;=N5lx1fZpnBUl#)>r}J;#AJHSu_9Loh}!G9xyOp;|ZPD2V*3 zLMvH)T@ov}z^08jhnlKXOnFx71uG<}&#)h0c`yN^CWj5m_Q$@;jjhGmB5$b-qDM!5Yw zks7Mqp!w71@m{atnG$nRZ&n9B zi+ofU*$r{;TtSELGVDq3quFQp5}tb1;khM3_*v5*=d<^RSMFvk9tb592F{4{gTd9V z4h$tHp}YQbyvaCRhh9ZMb7wkij!h!=ikFF9&|OSx`vjjZvs@#u4Q|dB;|=dWhihLw zgfD4T;9c5FY1RbHe!_#t$G=lZ4#wk8yUA~jU@C4G2?IP&RP;?E&8hzQaEV*o@!NOs z$ku1FdHwTwy=>29`Su^y%KU{hk@lSZ4I?=GBMA3Qk0CohB#~9?X7UaWQI6&umJJG6 zOJ}v-!Mf#M7^}~ZsV={u*(VSe#GB#A+JEp%={kz7bH}i)g?LhV6!RlypwlsefAlAD z9?WxKZj%`>R2mM}ms$6_y#miMR^NmDk>rlcDx7gWiZ{o3J;)mTz$vxUIa}8Jz*;u% zuI(D6y8Q3)a9I@b>e>d9>J*C3-NCEvji|8C2=03Q0skM$WUx(%gy}_*!kHI<#X7+G zkUJ!H7IE|!e8Eqb9-`fPTa@nQz&5=vxH8`bgAdokxcW6P7RjNaT}Pl_{U>&_Ip$OS zMi?owL66+q7_7I0EL+ZUDHqS6?*jHezi0x#xo6|O(WT_2K_@DnYy*$dLg;*?1!0;J zboBjNNUiL|*)N9SnL`=cNKc0U=gpos&Oq+c3?iS;vQ--OVCAHTMi+v}p?6*=DyE0F ze-H{QU##UpTR4PQbQ{)Ds~=BE4* zNTebcLyO!q=qq9Dxz&x37nzFB&tyQLn+d$kYJi&uI_Pc*A(TnE3m27L@Sf~6<~nYN zomZsUJ7NR*b2&e~N$mVZ-QGwXnehgpi7>QRglE9~V1sH$wH0s*Ffb9BMHt))Sp0uf$n&u93 zN1KRb2_f4KFqS|#{V+Ba)f~6+^u9S4i@jf_J69^71EH(~XywgM>vH#C#uu zD~|?o;Q0eOBYGHhOHbj~r!VNODjO`)Y~<+|Nq|O`IpofIh+BKI(KEE4tXbTL2bJ64 zZ2xaC{&oTKoUcLOpKw^0yAaDp(@?%f7xo*)VgO@_CD~?jmOUy!EsTLc!Mzy$;1zIP z5fTf3&{?)BI5IZ}>Tirf=DRB1+PUhSd;fLgD&1?;_QFdH-<<~swur$B-L2%?=QN^p zVG*1kEXT@_nWPAeF-|i9IHQSRJmWmoR}laYMH`Hs7lOeduIRni0QP}7WM%(`yq-8P z`EU-OPR*e5d_5@i*cY#RDdDn)wV40c9b(?G?~=Cw*FL}-H(R|!@3ux{-8SJ0MC0ijt{)T@t8&cnYFNw?#Q?YPOl3P?&r{FWfti3J&f!UzW_Ib zE?|b(DDLWd$2(ENpRi_(FF~>4Bk@uAL1H)M;QY}zo?1mTeM9SEA%8iQ6WPXo7qxI= zkhv1|ym|KfL}99AHma0rLucIpEl`bv_Kg{+{O2UGv#}z*LBDZk{5VR}To}@dKn=fB z@p1Akc(^qSs=w#LjsoVdHCBW0b+<5r@s|uz-r~-+nIN&x0t$8V8^n|cOR zZmlJ*Gv=Vuv1DBL(f~4F%!SjeFL?Lv5DXSq!trCfuwttpRPWOu%5wr?P$VDMO&rFu zj&0x?wS~?RybO=)nG0#hbqw7ThlaKiU}eEFFAi+yxcvyuPJRw%=9X~%Z6f--<}x-L z;2ZTT_%}EkbniBz)gBMXQ|QKpx}{KedK4({AO-O_NLzRuj%!-M z-QDD!Xdm|e{Y*0YtDtn{DeSx2Pu`>rkapiQL@a$XwANfho9x-Bc65Y1agn6UoHN0} z;v+82eFp(-KV^1u!>%7Jmp0W(_;*&kpV2UfAkqYGP z_~phJn8DOPVieW?df~&~OjPz{UYDL%(6}d;KB=0D>1N63GRX(tEy+fqE|xX(@P{nz zPiWHO3p<2^fQSasO%IL1DfcFCSfK!C52wKu-M=(W!U%q<*mIl{ElFvx0N3)fHvSk4 z2SbSf*b(Fac9_B0v)v0a$7*ow1z!S(&3!M=Oo1^eWpsTO4N*BAxP0;~s0w1tCf+Kr z_go2jzw*IVI0E0o>P0b{H-V$RBVn(J~8qW0H9mHrf*EGUf%lLKf@xdX;r&0+pY z7kGNWhL;=l1~mk#@IjpnG^rMoJB^kc@tt89G1V2tL+>NsTFNnOI}STV5yjmcQ17K4 zOc9#`8c;@4LdU@45r2Y|t05#WVl2;UFW#9gY~Quq7Xu`7u~w**G_oy%Ug>AD!61b7 zoQH7CfH8}HJwSu{k1%EDZ@jlng0W!u6P7xffu@BSxRQ9NIJX)S@7TeuRA=0*p$x)} zGjTxnGrTv70Lk~JxbE9eo`}&e{OKBk#rK85^!$936m^C*fgT)vmNm(p$N=r~o8;%% zPk5c>MBZQUM(xOSuxvU$OAODHJTiGl>ll6PU zilFDZ2g>~{0xOn{So=Ez&beF%74?5`jebq@LIz+jgv$+~u60>ppH` z^uymosLvWFPaK6=B4>%|{bERQ^~VK8^Kke21boI9#i>8_9K;%D!`n{xF^Y%nlEEu7)$dJ9q;+k;KLNJ6-!ZgPeVr!yXK_F*VKBX>C+~H7Y5IlP94}4EAU?YDluE?1R zU&c?t_aA2UUgNps120)j&{>_`_${bvHQtczD6{~n~5CqR*$ zGVZxq!}Q28=$K)~ zt5-Qo$A1-)nl>MnS-b;pXTOC?_ZDjBDG9ntx}0mC_Si8y4UZZ5BcBj+rIR6Ac8W2p zUK*2&fk$xb`&7`WW@npzQ?Qc|;<`D{hdg;fuDx(JR^0T!+MTYb_|_c{$?St|f1kml zsUtYW{s%FPScaz#Yy+?SRuFOcNViP90*Rb`AboWOIxRSd+Te%#9&M(}Q!L@OrYmzI zvHT1Z?cIo>pucDq-WTzLh#X;@{mBqjzDQDDe=@kU+5Y+4>v3|>5O#mcgHp)?sJw8F zWt7C)%v3}NJyI@sNo z59gP9z=7MZiPjKb?D>5Z&%c-tDLQ^Aw}b=7-IFU!qsYA1W=`lH4)5$s@lhWl#e zbd|j@o+O>5dnkjQYgXWQm8t0C=!kN*0k|Z_9TamWVcMOS_@I3^B-QXinhsyWgW6us zdLuC~UOofWJR))Fnx(jG(R;Y4wVK!VG6zeheTN+Xv+$HTm;}A~xkod;Vm{vw$agjc zRd33&)#Z5FZ~)|%Xra}iT-NjNh#e@AkR@O1uxYG{lv#&CiA*)Vzqka7Kkva-5gXi8 zPz4Wk{lSTj!CY)2^Ahi&UYil-x0RFj^=y{=(HS;>QsTA555TF6U?3ACxZC~(Sr$`3 zR;tB86kjU-J`e@weP{63Su|>|%8+>v$5^wom zN5WX<(sTU5Oga%H{|Gb6aI)r5VU=jl2rEZles&o0n{ zgGqJRo$!_RAMe2;&v>-Tb_StqMQ}We`85A!;IuD$@Lu>YtZci4Mc*^%iPBl*y^#)d z{+Nr(2PffEk6hqo20%{eP8iUffuo6PbYDXi*vsr;eH|leajBD(pJaaWekb%?!rX1^ z3Sf;YUqauXc$E9Z&Uo@K@u^}u@}22~cjC9vynPbmrRibHQ$I|dtOpkb>e0WYmSrnz zv8%ru0}k$lXRNa_UegCtBj3YwzbNp_+0R+B%@aUB0*vM;k&Xd|Q&Qg!AAQf@@qZz> zM>83-K1M*d)K*xy--|f5AI0foC$ZnR1(zf@!K)>9=&;Cy8j1AbhX2ITrGoJGK6;F1 zdl$n{7vuLm_y8vsx8dc$Abca;kJ~2oz>dCFD4e;RJiWvidP}8XQg;)awYo`bGv{Gx zT`)?oa3+BRW<-g0dooU{)_%(jF3 z%p4SnrqotE8h70L!4WB##hG@LFc;1ic_FBkF$VB6#olx*W1@0*L!_FP)sFUG<)mPK; zl^ebZ(s6U6h zcbvfDG-EVBy2^WTDis4>&V`zt|KPaPce<-Lb{wO{e} z8Zr8A?*X!Q-3T7MvmURAb%RW%5qwBn0dK6$@T*`TJ8SVL_`cf*dzjni@$*UeEqf(Q zH5GyAD?H-RR*SyZ(#fyZI5hAUhVUJ%4``8t?vl=Ax9U}_{(cybRacPttB!L%S4Q*1 z9k=7nlZS!U%z*30O8Dt}JLD}$hR%88@MOh&&=%lN$O!rcdlSB6WS=nlse6*nW1ldo zJBsmfT|n|%C`2^yk&+vqG20{q*B{ly*5~QiR_@I5spFXKF$70;v%Tp*frJyX5+G;w z0kwX<#nbY;@b%k|Xg4hePDd1j*xO**#yA-t&bd?h#7DH-kB_S;#LkQcmr+u^kT)P7 z2%+AJ7?AY~w$=t?!_RoSSZ+4H(96ZU;t!yBnKtl>jPSqLX(+TGIh($*hQ&G;xZu^m z;r)A${HFrJ{_zwjG!un|cdp=*{$^?*eGEhw_fxfP5xe^Cq=AOJ5Gu!~f?8@nDDR&R zBO?a!ZPJtR%I7lBcj>1E(skfAPk>vU(Lv8fOOvtDa_l?#8;j*uqoQ*NB;N|7)7~_* zyjMLsH`WsToe@7{#VYLG97?SN21sbCAB^Pp;v|hEk|1^vef=`AZM`kre=`C}Cw(w^ zWIrtSdJm@Sj*=S7zwj1W?=0R1LLbeB-K+~|>*53Bt0hranveU)*9GsKpM$ScPJ+u5 zfrJ=Y#-?C@4}}7j5nGjt)$+p3HOcaP`#i|tu}%b)hwx&}Q=ZZre^i|oj0zu&;qhAb zE!Qk257)c~mM{UE(tJ3UtqKLx`4dwAg^@i|oAK)QZ@A1#2+y8#fn@f-Sm(A0Rr6Dk zb26X0A7bu+Ln&zUH49B*n{eqf7XLXoq&AXjBo-y*L$) z8C@n#-Gh*Ek&AD|3NiAi8Y+3Rek7hD&Z9mMWXGuFYM`PsPbg(I#OIZt+a zn_jSC8=BRLN|eG{P_#PBJXkSQ3sCk8cXc?ZxBv+?#|hYWx6{d-PI2t?^MCWhvz^((Tn#%rWc!=8xd2vkhjN|YU%Wo?H6Te za@9Pn7cU0w_)(VO6i08`4U2*v0lOyxyGX{%Ixc{HXTC6oVIN`1K!Ck&%otJ zAubm)$4L|R^pA!-dZu@w&x$X&=VJ@)xiw5LyIKGUc+(jlpMZJCPUhQI1i7^___?^9 z_)G95{5R>ZtjeM5uw<|ca_XMpzYB}-bw)UV&2tpQ0ABuJ5bw-DG^D;;igK@RW62_M z*if55!`$+SV{0c34m^$y4r~vR%a4s3r?AN7FW}l?JQywt+r?Tzr^JN(*Z7O)^tAyU zF88thDa-GjiCcLB&ghJ0Oct3rkk#74+3!kcjfV=>=J|_k5zyF29p?x5_-GT~x zNx?)<19J_qxszlmaJ#sW7~29noTFf1oaF)(Q)uo$5f*%ogT2aQuq(F*MOV+`Eea0f zthfJ7d%90RIqR@r23IIF>;j+e8E{*y0xM`gR>MCiQx{0E3i|<0OXZ=Q?bog=o53aT zL@F77o8H=TlzdplL9Lov7!xf-$;tJL$`7t(FD9Zb?IoL<$ zBihZ_vGc3|RPV8F^$h&jS;-4H;>gSWcptfEy>Ys)Bbe9C#u2LpoEL#+cxq}XMAk|H zcU>zeCi=p;b^+4#?<3^!GH`Za1D&HJm=G%>m~cQGv3e|zs!T-lYFjJeZ`d>lwtkDw zy{YiKpNCtVN+B$HfV6yQ!gJzsxMJ`kgh$PSiPT<}b)}^H^mk5-QXtV1`c6LupF_Dd zwVV@=3cyTv0AEDJ;_3C3aM#+Ei1Btnd1?p9rN`kPw>kK(crPZIucsG(OoL~8lHp|Z zJ=n4^4maH%;H=*(m{2cs3;Ls)u#N?H|I0s3E&Nx&Ba2YbQeqCq0oH}smJhpBS|R^% zB)r`OSk!wQL^Cbn*v&TV$mN6756*OA)R=Cwy$Gs`q46(_>uAS2H*BBg0dsT;;6>UT z8ewWiFTZ9T#WLn1s5F-K7N8I(7|A#dLR{Hn79eeM3U|I3Mxnlg)NlD*%sX9)+kfk^ z9a0!*w6w$2$v433pb@o-aKSQe6ukT4M~?Jdj=Od_4~A7tF>zM~HqCnpb9U;3#xxIJ z_KO^>Hf@HwI6JiS%!A22ZScx^04oJ@i5h#SXsCzdD>nOeD!$9Q56vKwdPDY_93tOD zH{i?rV7m1?PI0e=hFJxe{LqJ2>?*)58w;jovLEotnR3*t3m~Vz-U3tn4Ncy!=(by) z=+^3uGg!Yagf4~KwX?xz`D~o+63*@uKY8U6Ce%@?4t3k#!OfVLn6{vV%vN>hSbOK= zlK2VS#5$6;Gdj+WLwZs|$LolcsgQl!rVi_Tf(yy(sF}U7GnD^GQ0vjePg3|RUqE}WzT&s)V`v!SjDO8T~+l%AP zJHzqIJ0pB%B$$xL^3dfr|H#1_zJ&H)JeaAOP1Qf}$jx$9@SnMwPM)+E9zM7PuLFAU zd(Rl1!@B^t)+nGF?=P&}GtPJf>G*AL4hX**K&x-wkWyC0Ntws|&`aO&A}6YF<#H?9 zwAc<}xbt`A22^1F)7iW|EwcD$g%G%|zYLlmtk7$I7Cc)1jDF8ZCHZIMY4iC{RQymU zMp+utbQMv&r7i=`h0Oh>X@oy}LvU#Af2dawj1fV(SbR#5+KDs%!*pS?D5@KV%ZAbF z2;=P-t;DcaWoTR}ixr)W-LkR@O%^NyJ>g=wnCcGmuMZPnvrIU%vmeR|`4c*uQn2@B z6SRF!LCzOlEZ5HgpG6mmoPsrsC3QiT)IwNt&zOiR3ew_N&b*F>aCmlg0b|k61ryVH zEb$Novs-h}wWkwT+C<`+C?EJ)!dSjP!Xe{9D@S0NDe4aNz(&_d@^HT_&Zl<;__E6m$;m&%=*j=T0K>k!6(uv#q09mEIpw(eZwCn2oFx{@?a;Nj zo@$m;?0>}eO!1#k*(ZlHy~-A5X@_B*)<3*I*^Bv+XTirA!Dyd(A3}mQVpwDyCqKy$ z_kT`;w(o6l!SDtyYM4m`=h{I^og(~Yoz%NxX?XYUdvxiFgRjS3;10hln5S)nogJTW z=A2;kT5$~SFDryYKTK(5oF(py5~9lI-ed4Y9E@Lf1FK)j=y50vSA3HP!F>eM7e6Mi z*MEaA4^2?{#u&O?h=-WLak^1~FM;RoLW&LY@$lzrm{jx^t4;>+mib$v|JDz{-Pp@I zc+5#UQ9#75dEwKE>5$gD2OhgS;0A3mjDMI9ZywG>k?c$|KAU}G_x8g_6)|wqmc!Ej z?;f+vVTapZ&YqG+2=`-d@Xs>PJnc3|Z4 zdkh+lDR{hihviL{)Z<7S>z`F1-yLu2`&gZZH;RGE>C@~k69uhDq~PKyio(|riEAva zpqempKAiWkdq2G-Z3iPmsx*I182&qZlP=CE#*xz>iO{qTe0eg4WkP4O9;hRR@WJ$ozy?Ax)&&#*e(uwT47Au@0jjq$ zd26!j36)(4YR4W!EPLBN(<_zd!2e?jlPb$Fwb{VuM&rbD~+ z@y4QjEZ`P$@?=k8^vqAR#%vSZbXUNGkNCM-#RZIW(ah10%D|0PA~63NU~soH1Q#2@ z!!#SBwKWFgdZp;b8+UNkiw^uHSxuXoOkqOrG#cCTack`axDT2uK;V))1niJ!4(&hj z5*t~sNnR6_NB&^0p(h*=wt%KNMli*A7ii4egxUoMpvKz-YS;h4tiL?`llG4YYK7qC zkwUzwdmK8AGvU6tARM~ZjaN^sf(+>Z-f1!dyWID~hFmwiAJB=L|EbX2<)5MHmtcbV zTpRGZC&SLMso;Fm7|*f&Hq}=`o${yg(@$&BsKbLOt^JT1o@|72$x>db=MS(p{K)vL z7OWqd#<{XFmRN~G~erh#^H;21uJ--v4{!~F{tuMeQ)?w6Rmjw#-3zL$feh@WR z#n0>Y!0X>q>P*j&_UQuL;2KF(TOq{0-Hh?45|0NaCzFP6fiOHZiBoOokDlW77l2E9I*6RuOctN0MX}}Mm~Xa;w_xp0*6HxUYyUj3 z<7zT;S@*o<^8(bnS&MMci|uD)fv+CYbc5oQPGx(e)F z{ug7!WpP?FV_i%7qjV9EH0y-Jho#KP^wFGTR{|9NI0k&aS+IFQ1N<~fM#)G5{coIL zbxSII>i&VlZW=I}yIvQQq84uAMzvv0ES-BCG^+n4@tK_5PTVW{s zatT^=ym(I@2ylC3qj=x1>;Ox>7>?5WEDW`X#(6S%tmmhIbMDK7%=9+sC$CWdXfPPW z<+9&*ANzf!V9`1^SikKMs)oJ7jZ-KzUpR~>llll}$r`K)jKdXPC*U_Q&q_x*KDTKh z{Tp_nc1|5+iJU;q<}W0Gst_ly8`NMj@LEBf%zrk7hxUJ>W{!8UOZy2*2~y^Ow1ZGl zM;KKUhRn^w#QCKg&iRv$$6p4(!r$-7TbVeV+?#?8*+ICM!9ltVf@jJZu>_i)TlAiADcio^tG2IIm@f+anyvNZ@x|bj_MvGMXUm7kx>; z@CY98cS3DtOGvC5M=ymAn0?J0xj|p(!7ZXNns<)4|K#V+TDk-l1v-+YQY)x;yC_!f zafa+RXRy|7qW`W&kw)l?c%JpsGW`wTyhu! z`SYDH+86>g!udpc?+DGxHiu7)wZwVcjo%M$C#xr1=}=bsF1f-(XnwQ^Mz?n0j=E;D zcf((htY+`gNfV$n5RWnm;WV+sfXYS{lK-wWpvjqf@;5vYuSu?;DDF|8PW zXe7e=5@}u&+bK-mdYST_`-4~1N720dAC}m~LWtccSRP%7mmd`3`Tb3>!u~L<3o=F} zujwf6EQ90O#V}tg5?>gsCYFcZqMNLbtaYFhwenbw|HMNf{u>wMZZw__-Tfli)Lc{Z0~5DiAUaz0v%} zHn6rTp%uy5^wH*S#%mmdsBbcG^PL~wv%CRSB}%Z`^DL#46X@*0cF6P&9-!Psi{msd|p2kVNUWhJXVsKHa z6q8;rg8PvowDoEzS-T+@&R!3LJc$yjY&C~<-|xT`X-5cLqQSUa!SHLkI<~krKuB#P zcAt-iBLW2wkYEa9x^{4B&m6EnZ%hW0U*n}8%ixq|4NMMh!bICwxP|rHWX}XbpxiC+ znW?hMlN~G#4{Zb+<3F(ZbZ_J-S{j=T7p*nP_~h;AQ2m28N5sO5(7ovTG8!WnPi9Wd zG)#GHML#X9rxI)@nRGReraP@+bC)tOVY@Gzolc~zfX#nS)DV~SSX_JW6uj;9f~2}` zyt2;_#ez-fZY3|`aL^y+UmXJ%IY;XB(TSekFoMs@XW(&df(nC)IM+KAZisHe-SM@I znTnWV@P(Yd(ZG}NZ$$BVXQ}QF5!@BwL2e99;LelXaOUbHoN8%^30-ecMx_!qEu6;j z&jVbzNCh7o#>!r}^oGXNFT?Bii(r9e7l?8-@q2SPmKYj+qtQ4B3ngBZ2KSQ&15q8hvLxm+1Fg4$uvsSAK&yQ8$ z^vjQ6Qf(~>s`G{E1~YKk{RKprEi_2yQ68Xd;sH|~>!gD|3^N$(8 z&5~k}c(WQBFId5(qilaOs|A1E%_f=KDyTvX)2juQFg|fi{|*?ZY-xU8)^kjPt@hal67GT*$3vdsSmN$L3Tg=S?C#I(%HElXmE9 z`HgIODhm#lF2tL+4U=CxrZZ0~=-D;SIiM zcsaZs(yY8--`Zs?n<&5)?W%@?XSLvW@e5S#c!k+EIe2>0NVOB=sZ`M zbt&bLyPq$C6_tQ@mXDiwoSk3VU*VWv4aqIafGhdac$rT^sKV4qVB;_!+OJx}+bSan zv8=;0smXXQ+7w$)97gLmnJ~^5M!oFPp7Su}98nYY{C1T>M8z0lX#g*}ok|t~~)4PCJOTjJy${bG&iMpZBK~WO^aJ0u_r{6H_{}<~%8)9}q6Hn`361Wz;gMoxY zC>h-Xb4qO4>}`w&>db==yS#C0Eb~XHU4fZ3&)~A=F(8YU!ur|;Fzb{ms;pi{o}O5R zvNRA+h`5j{Z$50%)xui)Jl==wznJW^44;_HfommxI2=0;j%Lcd55L~fEpwRLeOL^l zwl|}f(Iz_l!5@#QQrP5e4SVSX(x}urphR)&gP9q7Wb%?DP?=hCGhQ2H7uS{jmNLBv*kK9P*U~7&0pPc zu1X0+4sD}{V&maid$mo}#fcQ2Toh!>c z9Vx)C7|XHZ1fr7|W2TLA=)%Abl5kamnq9QRC$6t~BDHDw&2Rxa>|uG>+BrB$=Q3>& zNabAJQ3%T)n8BTRGrG`lI#~Zwq-B;}R14AwhwZmKq;kQUo&CzRoS|7G1XaH#QsJo& zs94NzI3x9jwlStr=UsQ?Sn;F(A5+}@%8QB(y~4hRaF$E7VhsBlobBj_y^(g{J@CKQn!wUACBe2~1H>ofD05z&n@UedtMESemRI-KU%8gPTxh5>m*av0O zJQOzD3Tg+;aHb@ijXh+Yt;BJTZSOd-3Qdgv)cTxmIMf6;cPOCdq&cW8?!c>lbPvww zG?Je2Oqx4)m^MVFz@_l_oDGY1^URg=$#G%#2mQp{uAG+_g_A4w_*l3zBB=E_Y1tG+;GhI z`T?h2RZ$NK#=Sdw0$;n1(aHmZ?0H+_ds9V*@_&Hpxm+s3GFj_h#^I`jcw7_T52{Ce zG3cBiJUF%r-V0kp#d%lA^jm`_oi?PnF%sJ2Vqsy)IGptT4$bYBpy&J?Psi}H%up4U zoHD~+fjOl3YAZ%xV()IU3+p42Kse+LC?v3%`sCm6yK;i2Iy<51EiPVdQ^e!Wp%{K6 zABLm}wkr(~Uzc_8dS(XI6Lyl7w(r2Bdh(!E+Xc^S9+2Gw^6+<{3_Ut0!1QkkX0f@E z4EYajv;TnSgfLP4PZ}??8KX&NB}v|93fCbQF9zO+V?BPHSE0R(B>Rt9UaT~%Q#ss6()v1(f~=Jgkb59h%$()mVd>)N((@*_yVWV zF@%N;G$An;p;|0!&-W+-Z&-Z7{ol4jW{5qxolp$t-m{GK_gK)wU{pKh4>Rr$5aADq z?oR-=MDuu`vaNCL&<8AWev5xKnPZ|f5pM+v;i*qsVdGOC-fWGek$sM6D!C51?XCEK zr;*O>?bKYU4b-pvhICUCGEF~_+We2A^Nz>zd*is(5|v6@QZy-P@tlijD`|^{CP^w9 z--cu*$;=2@S=oEUbFPO9i83=PyU5C>Y`^pSzkhl?xBEWlx;~%xyIl(JC;Fh*q!h3` zpND^Q8qsx`C!TwG4^F5OoT|JOD^>ZF?YI8M*%!O;KP6j~i+%@}T%8%0Plqh6 zR;NGQoRDGl;iA7ioY?skXLIL+(5z7A%X^8tl%jFO~_aLr@_NOTxYCnqnPv22F zCj%7X2=I&X1-<4tYek-VroDUK# z$Cj#P3Zg4wu=MUFI3f@RoA}f@!DE$J%9y{4a}cOua#~|4xEOnJP)tN)Y1^ECi<*b1Hb&$ z!81$N;iran^6Ke1h*0yyj!j)yGq40DtAcTNxf!e+i-ELVR`~049B>0>!$z@g7*?4J zZ}_Sqi|xZazqa85jeaoR{SMdYU8UZy{=<&hL#V)i6AP{E=xV(ZVjUO<3Vfq@`IH-Y zF7={QOZ_2Wd=9v?_XB4_m~Ifwhb1?%aBb9ToOd_`PU#J!h;kbVeJaQ^KjI5K*&Ixm zB8GdOHo)(Q9#W|l> z0{^ar^Z;*5dadUhH%vbrHO+qFXTGJ7$NC~I>wa*jxcK8TWp@7@9zmasc-XwnkgImA z5Vxl`QrTY_WcyNYoH2hV?hu{?Tkg$3qkKNz;`g^PVdhV8+P{dtF-QiZyX)|Cat2O6 zSpcGBgnVQ>IG)unT==e%qtKm;+(pe)Xrl$@D;FW(rHe!~V;r{b3rD+KQK+>s6(+Ac z4D;J7$*QNXU~h#GUSZ6t@sE9E=bk`r_r6RTZ%_{pS9HRKe{t04qdk`Nhj0!pl!O&E z$r!6yLHh4X(#x`LAa|@CmAJatHhv%WTw^Xd1zFU*Fovt%4&uU&K$y*)fL$FYA#TVB z=?fE*nCM9sXI0?I@OHTWum|c7Ws({7nT#DC2YYttLnWULJ}`=A9`_ei*hzqhrG5s3 zslq5C_X{^Q)j_$71a7fl{j@nB@Rd~@@=DpeXs;z|%oQV(ot)?l6XuItI7pAl2!n0f z2+rN4jC58X&fI<%Os9Kssy5s~cN50v4s}MO%EQ1__C*idTymOqEZof)U(To>KZs_7 zb_S2kKg4|ZYZIZ6G}Ac``(P+X0<_Q91FzyUY2aC)Y20#Rk!(sVu8XkjvjL8&%_JsA zZE#;2`r} zi#;cnQAyia&Z%`;Z%~@kXJnsg=q92#>`#L+EJ#Gmq&nzKe&N*m`9Rp7- zV0|Jd&{-CP2Nx}bU7Cz@v+M(0PH!O}bWcNCPGi-PugDPO|GqNO|M8yphQ}T z_jYkArpK)3YJRYVc+W286cbdwbN(D~|MBxwwSq8YdLYJx@8|pqF9efq?ntY&QPj-^ z)ZT~D2(RZ#+nX*z%BnIr$v=!`cjLH^4SZqYyeeEVxCG-?Z9!ML2(V#1dV@MX<@ukl zfSkQMY0-&i-^qQT@z)pnJI%rNKj2u*8-nC@>rr1XgEshbFjg`gWcJ2`O4SUEXPNej zHQ%{zze}-ZM>%Y&Vs4zx{x~`_436z<0g;cD81y$2ZmHO#p1Gj%Ch=-aP%4Ef&C@xG zb>3*u9gN$gf1%tVPmEW14OQMsP@F8N{PD;;l<8u9ge!Mo=V=QvRm>QV)|685g#|e6 zRw>?k_!exuEbwBK1-7U z{_s$;v?v^pofl9JOeDXn=vV}r?Y{x5MvWl#iZpmctDvAGA9Qs!D;Y?xgsc7UQ0veW`1zt3FZ$|Y zPhBi`!!=>_>WQIyil)=3&8z9tYhF;E@&JC=xuVal-&9|-ncO|uL1+Ei1i`ca!+RS7 zamt1JbZpE97N67P+?QVmqK8Gvww6vZQ=$xFb1O*fN+7%1`#~!32};T{XYq?%Hjf@hNAVySj5kdVaH}J7MZ%ytB#Z5mgpJmubhH;?Nx9A%0PCo2gC|2 z;kwpqkb4%&JlM%N_SS{?lo#Xii+#i`bUh^7IdkWW^pPyBPMAyD(tjs*gHN|Nx-~P2 z5_4#3Ke=n9r%8Tel{H->Vv!8f?OyRZ)Wq0-uO+PZ7-hE5W&RNj&|eMhtA# zy@kJ$NAcsbTO_q!9Bv-^PUTg0Vy}8Q`W~*v|L4NOovzT?NBMZi^Ucsyg|YEV_JBrO z8ankGlao=8u*X3W7Y9tGeY@;I)tFEDy|@xJC@lc@!a}xxDaUQPb2yWhIU@H`B-X$9 z2qGmtkUcw@ZX9x9u4;CN({aEDf8N99^RGD~9ph*R}=(*_@Z2J-o4=3qB>(ChfnR6D!bw9$js6gB>l0%kQMx*L3KbTwR z#cdc4g9o_%zG>GhnO7RjAY?k$|rIZ zFM94prNMHjf8GO)8N0Ail4a}TzN75{Hb1$M1RFj)geTlB_|3x-MeZ&FRiRGwyyu3~ zA4}s4uYY8&-wSTdCQrPbcNS+Qf5GK;sn|2DMl7c9r$Wvh-G8!ScW)M=yiUh-@-dH5Bqyxd76ZxD|u_hEWN1~HPDiBePC zU_3zr3obWM-=k_cHX+owH}a%Zuwd-I3N{9MuYU+%m9V#}tmG z@1qgVT;Po42n{zrjHOk4%G;NEf<);`*i?HQL?ii?W*Ir*P+}P99_mv3u{|E5QwmTo zd<&dkDX6@q)06BPaOb{f8E*0R3z$&zp5?bcqNElJ!Zk*tEqF6WbUzXyH4D94;F!S0(s}!^;DQT&(fb6(%%L*>uuK&LUi9IUCKKGS;~AJe?&7|g(n+q{>odn$JS1MV z!2hO>fv8#v_raZFth^zhyr$9;7rN$Retw0ZZ-{?EKJtv7;^fui z)WH879A*7NXUp%@E58qZH+zEo4n5o%xCmT#&*Kb88bG;J9dx9O(fF{9+2$J2gR0cpT%sMqp^^6G-)| zgw=&jz*{{?tB*gzUXw+zSn3z9T0TLgS_G6Y@C)z)W1c`xLoj_E+X@xB)o9RU0(#sk zIFnQe*Y}0M2p>B)*G?vNIfY7vNtU?cffwEs)`9;F+A*Ws4N6xC@?zsEu|3KiI(7JY zi@sH&TAnsOnNf*K4eJ!|>E7VZ->;6T#_W8k+DV6g{vtlz&(TNr2bPi|G`~`UvPu(> z;b4o3MKS?FHM$+!;Qt>WM%gbocFx|{531+8?hl!DrrU& zhj);g`4cDC_@oy;c?HEbnRs^n4A|S}fFZWb5!w2KGjKSITA$kn+cZBDiTDieXPJ38 zJeW_rmK8v~ZYHc{HlhF8cHp~5$bJolbh5kv%xC{KsuN(zX z!_O16Y6fWNkB6}LNGW#lv+M-_Yuuv5g;%*x;N9~p@KTzGlB0as=Acb4eP&L{`Ry!g zE{F-?6ZouB1~k^qhUbf=QBsZVl;_grKPvj%ldvO_a_vpa=k2W-S`%Ju;)D4?P zJur0YDTKSy*zq?N3zjzH844s#c+pFwXIs$=tfJJ{&;l~c7^ z8ujy(QM!zaYaZ0m+ym0!)m}ioo(ALFU_o5GFp~@$*n)LW5^TCri)oE&jDt~5-;1zk zdf{p8Xu1VP>`vpoww*bk_~63&Q4rWVf)fCsdVB!(FBeeG5crF{d@HP2kOa0he?c|M znyx-J%pEpN!pm3zo<^52{Wgz&|NIIRKl3Ro@)g6x#3*sy`x4dd8i~#Kc90daMx%>K z;1_DgJYs9{m0Baw-7JX2!4djuCxJuqHQ2a}Pg!sKT;^Xt3lHM1g7cj`c++u|BdIw9 zBz#o~_jWLB`O-y0dU}~7KnG8&gy9`UbG)MVnbReDhvpfWv-6oau8q}#s>hd5ero`n zWNgqlMM0j*FEe`QyFUizx`0AZ4c6S-4m0^`NwZQAoqjg}uC&JzWl?j6T?=5mn;5cH zItCuJ4&asMshsmHBkYl|0~R{$hs;-b=;e75Drbk`{1c(%VS*I>Jtv#Gs|b*V*$twoy3dRj6lt<7m9Z)!?&DKT(`!V-hE$3WG}J({#iAwyc`X2Q*yztBagaz ztwU=8H`W6>iF?eG(;_b?&}g^QSf5e{wp%~o%wc=1nmYl!QFg!BYK6IuZ{fp{59F9r zAtX9;@PYqZ7-|p4ML*v`eqB60@TDKcKGvgw%nj}dXJMQ#e}&uheJ;q&Q=_iCKLKN~ z(T-b%#C~!iFkcy|_+$W=goSwc`X5GptV0J=E5d#34!0g;K}~-LsnK9eJ?*1PUU62a90KgV-|eFmdsDvF5TkejT%2^ZXrr0 zAN-5oo>Za2_uJH`h`kSMKEk;}VIaQcCkU&G5IX}2$daCp(+_(gZ~aObn(>TvBM_>w z4As7*Fc!&POpzMm%j<=tE!2mzT>YEdQK9($#p6kI}x?x18yb<4N z{#BYbbPYr5_v5EcLyET(rsJqw6)4&7rY#j`h?`6a)vb91ChR#WABy_%>CepwXN!;Ln})u zMrIP4O88*H>R0G4DNAE(_;{IO;fz7?6YiW}N`@ubtS7^i_^pX13rYmBuGb$tz9itN z|73XO?Sej$)=aaq6{=Uv#Ph?2SgPVjMn14}+vII{I=GE0q(;Ia7cPd}If?hol0oSC zU%0mGHPvpngHv0T;n*89c=JXW1~!zyy0a?y>ETr(`!)~X>TJaq(tsM+LS+Ul;lYY; z)WR9x<;>OTaJe1&nQ{V$MN?f|%z3*>7rPMOIw&gU1!V5P14D z2JKG5ogY2$SV#tRta?m#OktkutRa}`R7I|Bxs1n(YUuDzb$FsRf*H~on8Mh&wPsf2 z{o!wf_s9^yM+E}4x4=rVyHG0;59(*j@bGjEx@1Z|D3+w5@fs`g=nOxv|8y4|OMC)> zWes@G>m3Z6+5o6I;5&tGsC8%riOpm1{jC@(&&WkHt!?z=@=EeAZ#~}nuoYw<#)6q> zCG+w$VzGJ{28GJNpKTVX9bblG8D zTmFT6{kbdN%3J}1_mv?|TLm)3WMSH^Npzs77}STZLz;jMi8{x6gj+A+t*UON;E;ci z^0@>GjK9Fsm25{j*pD}gh2f?X>$9$U3IiATV2+^zc)SWn^LiDyu;n+o#m?n@+p@{> ztdIEfj4mpi>43u*x=350HOvfbf*U8g@vy;v+^PX<46k>3v7?^0F&OA zxEQX|s(hkF4*vy-+4I&nWgS`B7mS^7p>As$<&sdK^9kV!# zd#___UJOcv#iG$CT{y1qPlj9z!L;Ws^UuB{Gji%cb@vE7DOAA)M>R0DAs2hcy6Mkj zmgsSR2u=5ofP9)ROwo(MS1ij?Ymo#;)obYEstM$3pU2;}tlu7$hTkq!z)<}>=5Gmy zAig&^=TI4ro~^^XJ9A;=!zOY#V1ir`(MjL7Q4FlvoI%B!&22@zk%$DqGx7PbIIsvW zT^)y+y?L-GH-ZF@x}owqE*9!O04K#^obq@B9$M3aGuFj{t!@YMpB{mmx5}vAV{d3R zOu*sFM-Y?o1f7pQgK^6MGWkjm(u?2VX)t3%z2+I&s{T z<~%4+^8)#gM_^~i1$pxpNCW1!pFEWegpPS`^W8HAcAXi z4RKL{GqlZP*#~(co?38zTIo$AYW!ClM2@`x(Zm`kOp3u39BXumSOJ$Ed|**N>pba% zL(a`QtoF{q9l4qCZNdv~|Me!9*H6H;J<+Ii>o8Yd%oSJo&ILD5QE=GP0oQJ|Fm`t- z$g`e6%=xeM_4W$TshtYWr?-=S$xqykvs>`sq^Vfi{vLM-F(1r)A!R?yA^7ofHhebP zi^C2HL_B{JU27podzF*0Ipzdps@=u|Ta7{Cr76lgI&;;WLO^=@Q@B1?P}wSMAJyI) z1iZiqxIFD7rtTAmH7DD_Rm+Cz*EfTcYZ4w_SOaS#OTorukjyg+1k*%S9F+S(E&m;) zZcq4>o4uApbLM+A4Chmx#0kdHff(GQxRO>Zlp~zjI&gbc3(`tOupu=C9(szQ{$2}c zva%oq+TieTHSwE$7A}URf~;pM+BT`+kanmOLgXpRlb zqm3@vT3KGrW?}xEC9bca;9>@zD1Cu~rJbB+mS?{+&d+-q?F3)6E)e5e%>C6|4q7pq12T$$V}j$Q`#t-l7$cdGb2qWRztYVwDVH$|Vs+eDHR8^7bbnm^RY*cay}4g<%r0Xsd+P-HFhySTe>x3$y~=fPr} zwz?6t4+Y|1u~51?@m`?~%(xQ?EBH2`MdBN3{+n_8$SB@m zeWstYn#nwtRhE@+M!y=?i=VWSZq{og^`5)QsvQ>SzPtd>d-5q;&hW;x`=VIgcL!5i z&y)KbXOSjjMe1Pa#By{KBs+_Tj&i5qO_>GoR;9pU&1mvK(~q>AGKZo6j(~^69OlDV zhz2`j$oc&)FlFxtyfg}>nm|x|0Y^IYEM=_)B=atnXo~2A8fa{ zg1aT`!G`(XRr0y;@kS!_I$7dpttePETV3^hipW8P;iVvT%^v5Bb z``#X;EV(dAFbTFqUM44^_n~#p7{0px4L)72z=e0Fg6r2MuNJ}Fs|S|2g`tY71o?C>0^XNB#S=z0>|0ZX-rC7HmG#UYG7eG1y!r4* z_%{Z>>!ZS}yCCat7yDkHVNBblGC-8L}X5R`6M(t`Ru z0JS?SV1D%^(3cYA>A0K*k3-YogNhVm)?dTDC#zsx5@Wer*3dpdPxRen2bxRup`1M@ zvi0w9)vm>`VkP5pWRGLH{Y#Yeu)>`$7)N+N4}*&{L36wjbBCNkKCcu-#iVgsz%_he z9fwnQwSdr~>2y^E%k0<`!)vW(P%wM|zlSYJOpP0itaU;4{5NzU^BT(U`J*Hks70qc z@tEH$kG8ds;$ZUv_HVdYc8YoI>#A^l&`8xpm*BPI# zItuBoUyK_d57K_RkfR$5iDNbRX*T=)*RFt?1H+*EK?H-P`@n1N6__Pfj_-??va^#N zl@7X!>)*?8l?7>fXh}QyariaPP3vbngbBKLWdq!CcuijK+=gfvf=+AS;GU zrJUAG&&Rq$3t;R)09x@I5zklcFshXUq;VHS{^18r@*Q6te*PT0KITQh-h2h zhO%j=X-`TRZuN1-2)7hyb*=`ZWrIlM9m((gB2d<5hz(mT;982Hva4zi+~XoS^?p0N ziv~3Q{esA+AB8~s2Kt*X60M!z;{w+Z*jFUVJ-aCvcSj!Q+D+2HqU9Q-EZPy*G`#}N zO`nk-$-@i%{K_Y6++co*CnWMhIi_P3bcoG!WNaIV+BYj)?;8#Q=VyUeUL}^DwF1*) z*XZ68DzG%g0ta!>5@q2cBNymYPw4z_;6 zx1;~a?Cg!Wr@#Y`FFgnl)Ct+YHo{825wiT#PCWEt7LA272|8VbK`Q+;7*sxCyEZ!voc9|!vib1d=LMV!b^&vK*3%aA zMWZFlq0asj>Px-A?zNO0aqy?crxugu(2p3pISu$8q(FlFGq^F>iZjgHAXr5bw*-je zrS?D+yS^Gda$X}XG6C~|Pq;J73isQU!}%EqhaG>SL*@kRtXvEO&w4?T-Fb`N7}A&| zOW4soj)f~i(!GK;aiMuO3QtZaV|?quu)iAD{+7T)KN5)PXgepL}y63iaO4Igrk(Gix z*!AQms%Kb|k&3bOhvIAS~*Olm&G#CB}5dgp8en9Jb)5H4PfW& zODs=vplB{X2ND=JVf{b2$z0)yvPtl>uncarpGNsBv0!do2%CyKNS1C2eAL)L(#^y< z$8b6PZF^2uZuklR`6U3~*>2{eY{#ok7N}L#2oJtGz@6vTu)*y$+NK@Cg$3;UQ1lHX zH>cts(JcBVLLOFq`vU289dtmpA8fBMPJqjAl#2ZTAA$yGqRc+1gf0j?;fCqZ3!aSQ z%J+L6EV7QkXH9oVX1OWddb}H4ed6KAA7_qUmnbY-(G17>%praHSzIudgQ5l|a9Z*> zY*7)%ih0M0YX56ucuE??+FnA*;_EPwITJ4Ne}KQUj*}lRG;nLkYSO>=30x9SrG+CQ zxZAe_rYKavaJw+xlX<~7*;g<-wuKo0H;9S%8u4sKFHD%1!jawqrLI$3P+VCF@|OgIjf*`P#;B#IMwQ{f!C0^zufz+! zEcc<4jX&23C?Ee+#5vm7N@<@vCVIAzi}v4eo@EMW@bwdjsZ_;cdl%?9M#NBx=$`BFEfg-uP9(eTMjCC--e_GUr=ny z4EW?53VN*(aC)i*rdM}xx@tAyyv{n%XTSC3S;>qaIssRbUO~+|Wr&Rw;DufgR6V-PJ`%V?Z%s@`IYzkI-%gJZ!jKY5AK#cyu~_^b6Dp#W~DP2 z@1MX=rgK3jat)P}{Ez%iFoS|rN0_cF&OE;>v1HjJvUl_$eJ!nrEfS1@(Zu%h_1$=k zUc+|#399nN2oL;tlg!_i}udbvdgn-*CF;gmD+m0C??xol7^T;I8Y6Fs(`r^1>!?$=^^i&+`J| zSy#gLM;$O{RDgHdC5&EQM8NSY%Y?rg#h;aFwqBS%Q}kdiW>QmkaRrXAE$Y z@*#aq?{s7l8gBaiuQZbWz5Z4eMP`nOq6&LXNble;oc*W|Q{R zd7KL3P4(55fc)4ykey}C84GfO0)g$&z14s-d!__jbvTEDk&=urp9n?03glboeeO}o z8HDdlAr8*s$J36R(CHx;H~O4TcQttdk468ZX~H=;;@FDk80T=g;Zrv2PXk%K2n^l! z4V+c&Ku@Iwj=l_o9T7{2p4%90dp3lj9wAt{!2wk0E+uWPQks-2pnUmNAAMP@2}}0J z!0t%O*r~~k4|xn7LvO%wg`d=gK0t?;jCrFJ3RROTp=nk&R+T-bv8;PKKmQFkcYz;c z&fSIwYa77*$Ot|S+k#S8_h9tq8|bR{m|7RIx!Z1cjG3|oHNRJ~c}N6NIBtcd_8fXO zLKp%gR^gHF7vPoOVa}_FXeb=Hh%^3#lLDigxHJ6-1PF$~$Y%B(kT$|wrGEJMegir} zCKTtqh0rIWkeehzvnI01D^N#`0mh8+@Wm-BAHl|TgJgw?7^H?r;&}fg=z;r?a#0U- z7Mp;Bo+HU%oif+8H83SC4{!88z{2Bau(5(ew)JixCCd3^qIMgc+FyePf8+7mMn8Bo z{{;Gd(ZRs)!QXRd^k7X_64jm01$cNWeR<&jDM6mWnON89_F@K)CWXk9Y}?`!AL!kdfP z3|foKU9la-9=)fBAQ8RQ%TP~+i@q01v8itvOf9p4^3YVc<`Dy*99brO@_J~9%*Q{P zAyjWC>_K7=VWRA-9D0WV;#8f9%jrp z6~^@DSH3d(6s(W3-q6V)V*G41z9@Kx2QnEqvbi4(SJ%@#-wO2TFef&b&f)&6ONiCy zUI?C(fnNlzz`$V%K1|z2A4}b#`kCwuscp+O-!m6_!-rt^BS%j5v5Q1zg(}W7k%iXF zkvI~RgfePF$O*d&L9xr=rosqCEq$o=3{J0aDZvk8Qn2D{I@oTB!;7_o$|8Lla7$K= zu3sbxhN9l!vc4aOb`+CdTFM<1l!KX%hw<)2!r(ADB>5E$Q%jzJzqo)w* z%IE2Srapi@>;9sj#7fM(9|aCP9~jLKCe5CQ@oQF(lC}9XkT_t6FW;--_&N4G{Kxz& zKFn+BUw~6dA$%B<<+wiK=iQtcg;!SyLEn25VzWyQ63;%y5H<&nzd6i}GEnFblf~?x!6v?XxZ1DrS4xGiOLn?--P*&*6A3nFKB^U~VIay1n@CXAF9eB~weypSUl!h-5gP1$mZdF*&b| zH88d7AHpDUcj(9{12-FWoUwK(&bsdc-inM#*)M$fK6At1fKMC?EM;x6Vso)!#hh+U&FBQ`AfHRNk z(+?dCAubK!kf>-1rvj&;zHl<0-u939=6VueZ}vAXeIGg!e}dV7sOOEZ{qdE3ah0j&UwtR`tcPIef}% z7aYX$4X)t-pqn;2+QEH0UktT*4MKl1xc7)Vti2{nPOj#`0PO?8#zbsImPvbk8-@fO zF{qE-x9i$4^R+#;2Kf`O_mfbxbSoJAcEmlhNoeSm2~tAhpz*W$68Q?`Q;(w~Jh zM*dK(>widoU@hlCoh=$GjAMak7QLETjZkU^>*B@WbV@DEHQEaEFR63xJ8!@hk3XP@ zL^i5E8wKG-n=q1P+QMJEqAo5&ue4rLvmlyt%|sH9m%as)|GvPzf;_IqDJN`UJAut? z&(!xam~}gZLH+qmVk16^m(-c_(J2;Zcyox>Y#|ity@Cds@3HvM0ChUM6+SKL=UDwd zjV|n7bNEp?+PLk&D0cpQX(G-!cfA|_I@n_RnpN0+xEB{&JRzHgS*}U$Gr6_9hB*F; z=8jbwqoO@?z(-C&_1*cXw%s0v&pjh|Uv!YL#+R^qa2qW6!Q6JUs;S`6Q4TNe9K6hb zK@&w;ZXxav32)=${nwO^ub(}QCvVGb!(0rdn-5I-XZblFotGvVoqTaYKw;QY{7vpKMJCv@If`V;k zBvI-(WXJ8LpMrCczgY@qn|;Q6b8driRWUhpP!v~Jr>G0V*3%Z3SBjMv>+i(NMrRtF8 zLk3tryAt!{E5HpzvCM#rCM@$lv#*xkm{yB&YLoHXA79ck{vT~TkpL}n2asET2%ji_ zM8oKGGQML4+g;0p&`KXXDK3KEHE}Sl&jMO)8o`6HVeB~#==;OZJL+geEm*GI zbGDH3!kivB_DK`|2*ptTmBo;(@e;|~uk8KtgmWfLQ27nR5IT8}lDo?00IyuYZfgQI zgmu8_6;)_Cn!<^A-i?oYoNN1e?;kd!5ab!@O~5Ug`?P=G0T8^k2BaP`XHL>H`b+Ku zytehmkWmOUdNc#?3TWd#dDh1rGr=X-JV~OQ5N{n<1XDZbLhFwrWYEd0F_ zdv~N_xxiWQyY-zO`7?-SngLL1;fWs8H3U=z~?~n-NO-I z+3TY58-2_w*nsIO$=svYi(txSR}{Hq3rCX$>B@6+@R+S4^L7M);*xrB`STCLqL>FU zV;BRxf}r?wHGWnffzN7kFmT)%b_ayOU}hy(Ea*9E?BXGxa|@pOD}YhXCAhQc7`LrJ z6}3Ynz)brrbj&_LV%1N<09Q%;VQRKkwAVW9S>8G2gE**(S==2fwI z^X2K}!pQaf>%K}R2Q#f9sELUE^LIq3g?I$PXy*l>4S)j zG&cGt!0|Z}`13~=ZuVV356)c!VvWvVbRZcEydojwb2|zA%+51~Z`oe798!PPgSlZO z9GiI+{&`hmMEORn+nIqMnnkeCm*vNbV@dJ_esG(j!x$`=@KEpvT<6Co#!1vAHVbzsp#NsGzLcRL^afesYdcRE zvb01#yJl!B^QIp2IUu~*5x3>FaliL`MPfS-w6&R!_3Um;+SmmTZyY8~55jPbtrj=S zS(Kv|-2tn1mr;(H67)_>MR%?$mH+1md*?ZjfXmM~r3p%mlh_WW=iV^aPa5*qSK>y- zgEw`t!E}#ZaG-UFDz9O@8^*`kkktfV9nQiGGa+Yg;z^Y?L%3zaQ4%GTtnMn4ALZ+X39E9 z+kHU$*Gnji(}ewGwS@0^O2X6Td z((+5{AlS~MJ9mBr_k44(^fARIQ@`0(^)nv;Bdwh7b5l>uhf&D_K(B9@Ltky|GT|eg37VLuS z+m4d$o7-`xs}nf6IKwyBakN(JfWI|cF?Y-#+BVul*CRiOW!=IDRxv4~QKLA|Srj~O zyn~-9TsU>;Hwv(vqRhZcMfbZd(5)H9!Vw2x*IJ!Rxd_y)c zUqK=|X#NF%mqPN-q?x|y=2w=S5*qiZo%%nx z?_5IkUfSV=cr*O|We!^xPRENaCG>Rsc{K7_3VMa7@PKG8bA7v#_20hHY7H5B*zy{| zS|1vbosV6&(_yi38_B#`O0?@|qj$@FsGWHk{v^!8?Nibj*KRA=*$VPr2=sE~^OZm( zYZ6xd*GM*8R-%hL^5EIRZ*-kJ;}oyXg@N%DrGzDhuzl|_?r>VEqLY*)s64m?%CrFI ztPTbX@ga-~2XL$Jg&)L;e!Ln&_8K+f`R>>F>wY!{rKv$+QxiDHy@W@)^9b*%F$l=V zkWCuiv^lVp793d0y>sR`Iyj9$@@I-mCZ*unw~=Te?}t&gawsDE5udbupamF6_vJ}=RPf@p&}JcZS5iLl)aL@LPqw;p69s_ z2`O8Wne36B9rAmA|GHeRbK!i>^W69Q{d)DkV(e1yzx3ux1F$(`gzH9}X{eGo3HaQB z&C@(_l2kC;Il7?VR6ebh{SVp}SwIClBNlXSLmm4}5DGZMIztKYOFj#B)E|ZoEvj&z z^(>c-=c8`RZir9sQ`lykfv?w;z~EsE`u-B@HJxlD$`{fww08ntJ;=prO;S(=R_s0a z7mUi>@o-!Zh{&a2wyPljLefu#C0~p2-}xcxxZol_=tu|oW3@c}sMoNqT!26MVJNhl z_i$i+G9)g~#Daa^c;i|T(O%X}KYvn$S!)x~!94|X?G=+ui!PvRhc0fCjQ|Y`d1~X( zi?1K};`SXrcrfM@#+xjI_4i$HnS@Pp=7v_N%bdWvTtQGe{1;Y<_9lN#(PMmsG+s)B zKat(wj9J`N7!Op(J)#?E-`H>3dZ7t(88c~mzyj#(>LhXpD&eBM3q%TabKVyTat-z_ zW|`1mINsn5HX7&9V$oly`(+517Jq{1g@WAqV$84p)D6b}NRqfgK_YNpow$nZr<)FY z0awx-Yp1=0{oEhaH~0AUrvOC zr0DJKmK)$iUn%Ivm*AbNHaN0J6s&q9$xY5rxHaa5hfDgvcc&%{_tX+!0dZX5cmQ`N zY+yUd#gy~j8gx?YU_Z;O`Xn15r`{FM-gbhrfawq_o675&*hGqk3}LnKL|B;>58-n4 zm@l#!3>EI-iPe#K<3tJAb{WUz9t2F$MfNxL^iV`^XuC@!3U_V(it(w@Zl5RXw)fH`@N zT7uz&C$KTt5HeO=qwD2@lm0Fc;D-Nshg#yy(Y&LLe6tF{9-%s16J0~^Eic3@=}HjQ zt^m&%Ls&F@DpsJ&lDAo^rPKSAx)- zBG?hH3`;HSQFL@VG|H&q@?CGxHF-6xR}n(72eCMM|0{(38zHUDr(uwt@t01p#$&^o zSi!!>yEO>Y>XX1qHwt^-bdgEh-B9h81Kbi3=Fge62@{`9myuc>h-LS-uR%beU&)(tJ3^I%lg_n$mP#H{$uz6F#o_ilHaw5aC6?@xtCb zqO{8z&2_H9$eC1VToQr>(i(V5?HKuaG8}K)+<=5{EDz;ga};a2o&7?CBrj zk@_?IbTI(0v-`TL2JU%h4FWa3DDU6~iHucXDd|q5CZ|H&1dHV3m3B1Zq$@onuR&~QM3Wb7 zd*D8E2pmviJcAP~3h4S8Cf7(~yame!?J2{1yIe@$-F*7>XgTzqD8>Z}>ac%w59*(< z1L@cc(Dbw)+H6?oagQHvmoVdKzBhokKZ`Ko(G;kb9Va`~4}t2kAPnuyz~F{WsIKt{ z502*I%;0X$n7AwnEfc0`hOgoKb3GV{Xa|+BYU1fygdOI`IBx6PiS=C`QU4u+N-nwh zV#gOU%OC)-<`Ax)Ujj*nIVdDi1K0GU;qMera1O|!Ya)G7Imj38idloyMLRezVzagh3gx<>>ZKa+F`yvwQIM-LDh?Y2gXwa12eXa|L^YLUbngtN zCb>m;Sn)n>pGiP~FT^i7W6Ju3>tRKD8?MPug1bw!q2PlPRE0&?X5NSn6_Lp;B z&lKP;6lDCE#7poY*bPkDZ-Ir{E%?6D79QN~!to42euJMT*`)FmRXG7{7IGM;C%D5g zhfFXPZAW)@XFe$tLnm;BxZCo&vB`KQxo4$Fga&@#=f@dvwrrGnTe4yJ?-+6d@n9cp8{thLh;)4 zgS_Cx-@N|3WstYx9vqeHgkS2V*y!>ave+Et^|u5lPcMQ^hi{{pWH3&&ngvw4nM~a6 z2+C(~<6lk}+Hai)_9{m3>{=+ycJrYX;;kqUvJ6cn`sk;|&ooOW3s1hu#)Nn+Iwy<+ znNAwSC2Jg~9iEH5H$)WfFXYjH6RB`$r8_Dne1)s0(otRQ60V8Sft)G9!2A7^=UEd* z&Zd1u-=*|^iu^(DQyca<$z8k~l}t9f{0B#s`m zZ-mfy`LJTvM$Qr6dhFE?C$VpM;Cam#Djs}5sVnX{`{6j&t&^q?Zw+FbWGAme9?@@$h%V93@OOy1@Xb0d;KdtWm1lY>LumuK4134^&<`p=fe7V*EsY=74KMQ1<21dqcgwt(!~9U=K2Esc~^>1 zW#M^{FcRS3xV4G*EO9=h2MnO;t)t+uIv2JOmO+bLf)eLW!{g3yaI*bQIKRxW{-z-F zv;QRN=c_>SekIN`&Vd^e%o!}*M-us7FqZ!VruecMgNZ3@IrIU{Kdr*rM&_~ZtHkwB zUE$$)KIHE^LE_$|;F&q1aP_w-RIYx_IxQwxZx&8XQ=&O~y$NVGFAzpX!>P+umJ=*6 zz{Q6Mo>dCPiRX^N1_6JxuWUun<~r1vdIC2}P~3bCc~gTvlM~Zc;l1ly(4*=V&Q<3n z`~Dn+8&ak)Tc@3FaCHVz3vXO}${2=xf>3teEQqv-R>(<|feMG4VBY=@f6nuVs`@yv z*dC7w)33wQ^lu>d-XA}5qT#lPI4;}>@TXIpR~%cy+xSoz4GVr@zmyhwD>mS=JeIkB zF^mshpT}W-6mHuM#O+H6Se3T`lx#*-t_LnJUkFws+rWbSLu=s*oXj%g4|_&o&4LVc z&KrWIbGuPTCmJuL4C58)dE^J1lhLkJIA6UF!v7q^AD+D+)IJHDZ$E)l6~=z@wMMyL z=dmxf54kb*q|_h-&b*VRrydCK)!ruImB2{I7(c_ybty!iLMF-IKS~CSo$;CTL#Ve} zhK7Facu%Mn{_cCvxybfv{23$UKVC2ueU%Ie!fXclP?-PwS_SfaKEaeJCh)^F7Fs#C z;lxsw*ZXS8ONupsGpB7|9uDHl*sb`3o*VY#vGG_Kg^XHhFHb5ti zrb4ce2S%~{>DFFDT=+5w|hw>$IT zdigbUu;St3s1Qisi$sI%>~zJEzFHFmLAu-Few`0|)JP)B!(L-s_8hjSFT@RcS5de~ z2T!-(gWf3 z7@)WllYhy>4<~Dw@4@)be;a6%LLcK5SmV`0;oxwEWn`vI;Qrmx4xN+wU`zTd5Z`za z%fGH6Nm=>$?6f~!tLj1K7?#2OV;$ghZ;*2&?^3pEtqfn{$kF!la?SScvXotsq+yaGGiWzt3x z3hU6jZ81#EjUfW^3u*a_QcRK`;J%I+rXG;MP0j_-FyRX-WUGVZS8I@|Z-Q{M z3OKG?NsIC|v4C{pyd&{oyQChYR6KCy$}9-Z_=BAepK$K7eY{hhLj3%-<)AS79S_RX z;7(0LcTvC-!kvy<%x(-?>8(_t{Yb&5T!TjBe;Bq+)KKwYKNaq`TS_;KtjX<(ZR z)%aSD|Ej(4>`*)`nOu$&BRwHP<0tH)E*PGaiZ_gYgUQ2G5J~@sGY^eH%|tD1h)H2Q zfI3h!TY|5v1o>OM?!oog7f>na35f<#IQyk6z5AsJ%sWEhW9~1KscQ-f4;6%o%g2yVb_>z8iS2?z_N{6`P$u7v#Gumw{t&HNNf^B84}uVz#F* zKDECMV>32@-S@}S^|W0n_|D(_!X> z0xbQOfRWS8aCLt;mO19)+`d%!GL>Td>zU+Z;$EovCd?02%*Dmai@`MZ6FD;dJAB;Y z4V`zo=(5dSG^_7C?j6%06@v$%H;MI)&-T$y-zG@v_CTAX%-ieCd>7-zkaq4njK8a( zGhRf1PBQbR+6nR{U;5Ht5e<0iHiszQGJvsD1<;(5M1=oKfvW4yc-LYgjq34*ZWQD` zNYSSyyDf<8idzaB+WrIMg%WVC;R4*9$N0>qyRch``JL{udwkY1UT^gka)u-Tzo!<( z^V3P?T{~i0!#DyxCbadP1-4GLLCoI(!K3Az#rFrGbG0CsyIK!p|C52~_z|R4-tqn_ zyhn>u?nGGG53?TSvHS01d^2MdniWsLktN~K!0&)RPyOjFr4&@!xdKjH%f=(oejqqS z8@6qi!S$WBP~yYE9U(Jesm2z%^fucCDZOPLdv$7LZ3Z5PGO%^_T67<_rDJ+i;nAie zIHrC9pGSY8QA@wztSm%b%lz+8EWmS#m85vmBetUs1vjra zcu~QgE7gYBDE*p9bmgE=sbo?;v4O`14bbe`0g-c7?!2F>sGW+%n&@oyJb1n*VW4OZHzUOUJc8dVtPn`98 zKfZyhZCh!D(QWiU_KdL_ir~tofMkp6hxqyB7Vs?ngKNC4@y?JU<~rqL>RDGZ_t-E- zc{S4AL9akG(g&n!33nZFfZXccbhpS5%)kBw{KX7mye$)j14_vAQ*Y5tt%vy~UC~L*n;hCx z4mwhS?A&l4{QW*-9Qxq8yGc-(5JsX(V{vZX2o}^t;n_pWleK(m=-Zv2(4qJ}NSSc3 z_-`ew89$0O>6b8T+7H;(Ere;^xo8%&xQ`-!t_}DMLAu)!Hxg%(7GvdwmtvwHIOZq;N1u;_^DJg7IN=I;>m#1(cVLKxMod z#D*o24QhqZWBnCf@i6EJu%0P9n{jzLI6-_NzI&gAt)iLeVXKWdw*H0FF1C1b;kp0M zDX}xL3(L13rPta2>S5MlTb4WwiZ9rGQTz)&wDv`tAB*7Zzkaj~x5ZCqKPu4F3g}t4 zg__^xW5i`oE^Ks9GC^$Q|4Q-e76C(+8^bwiEyIoAs(6k-* z+4azwhj%c>jS)`S^@duin1RYgH=Os$g4}g4rD|(3;ADj%W;X1nhr>t6)*nsac)}*x zePjm6@3O^momL18a)bpdX2V%FA4+_k1nyG(5PBntEb&ty4xJ~M6IhnoB)P-3W;u-e z63coE-Y7m41wPYaaQB-`*r}EaZ$r}1XjC09`F_Q^T07>r>BC~xzpRI)3ObSlsJ-nK zT(v5qn)=!7In;sGcO2=S5IwdJ{frytzXQHRG#ouN69)p*5f;?oc1OU)GZ-Vl+7?%r zdSI4=9WDe5UuLS|jEIf&wXPN3-2NW)_GKd1%@r0+?#BJ`H8`3!jK87;xC&v+ z74bO*`K1A{AlCzzZi~Yi%#%AW)eLEFE4`^F%yrYBhS@^iuzUAIth99E=zd)S&(43M z?@XJhdypnP%ZUeNg9;=SnY`eYA5dD*5~uH6j}pOIP%&AKb)rmoYEQ3#&_Fh)=fpSI zm{1H6C4mTKKOl9l0ADXwfPdSj7@n}bki@JjWPgMww2G_HgJZwQ7`bPxQ2L+>+IBR81;+_z1`TnF3a8_8y>5C@KcDP7 zqKS2;C!x?!4XV2};lHdr6u-WPy2!iWS`PCU$r*!ftTQ$4iB8tLYfUC>3*@x=mZ7!a zS18(^hYnv0Aeva?N|qvT^zbE-}uTMMYt@{ zuCIZkcnVXZ_EU{-_wc~VVUniWgM%u|VC!NJe00?VCwk^!!Y4wkIrjWV0i_F-?o}c2KL^k6Q$sO0hvkz8dz@P@~N>`>q!ymCM`Z_K8 z>4z^bJtsTfS-|^QRrqwvYpj={Xecj2KVB$-8?Dh$cF`Ewr%m$8dHo>zGy4hUsu_V;=*IJD)50O?VX^U-wazlt+3X(jHHbYkuATS;9yb% zt~>AtJ=B5ZL|NdQ#5`CTo58GG&dnbHcvoN~ zav%7W*AkuK7Gq-8{N4ie7v#sN}e=!I*G zV?eQmIlMHDV49UFXGK#NuG>*Z?@klu-d?^CFEk}%)xWzSI_oul-qA@H?WmA{J3|k1 z(k9`CgO>PBcr`Rm+D2@xwMj~jA65@CAH%7W7@CrZ(Y&XyWK}D64cI~A`Yj|w&mVcu z>%q?M5L&EP$3GfxiM^OGw^cbGB)%sQS2ip5@L9+?vqJ*9m(c6ATW69y`V=QU+d(Q0@?ecwBfL_bhwbS`aOlu` z6q~#b?sa(LQ|4lD9hSq>1p;{d+HBY}YD6Z72!rL`Ny)nmt?>3&Bk-8}2Si-+;gz~D zx3(e#+O{||-rQQ|Dqesg>+I-B$y`j(w18oCTZ}%ukiOgL3s-9m;X`C9?ogTw+k!ek zLUlFH`m4ZM)wlpRo_|Wrg|pf3at>8}vYGbR?&6(RDu%avzhb?BHcZQ!1uw;#sNL>K zWE-tiFu0$>am-PJeotxKL4EP}iZ%HcCVDd~EgAvN~Q2eWOhcv>|OF3*^Tg%^S`|Lk^b5|oE$ zS2$EaM1U_D9S2+Qd7yrBG3=LN{O|X9@Zy9&_Kyp5wTJ%FOXiKRw$B7?%GBZA{bI~g zmG(yYOW!OGf;@POD_)Mc6Ur*;keRK|bR#PM| zufc~Cfv73xi5FDu@Ih7!B;!%s{rC%J&mANY3yYxmaTVNXXa2^@54dPZ2%pdX4>jj? z;sN>BL_SOrZ(S}z`Q2LZ-s3HdH$O*D>3Dp#Bm%V?u7K8kAA0qI4}3Ax!swAW$cmK3 z1tQw?jGhzB?AwT!ELfHzT@rm>e8ZL78aQ8AmNNg7AwB1!3u||~;DkbTm^Zx(Lgtpy z81po6Gzo&M`aakfuYjLbnWq&RV58F`;93>4&MZaO;YHweT?GVZw&3e+f1oYqJ(Mlo zjSA&?xS+oX#Lc5|c6cpgOiRF?X+zNdFPA4|D@2E7C-CEVc`B;iiG=#a!D%0`Y;5ZDQ*8-C%v#7nO2TJ*{j2`P<7eDvJ^o@qpy(9tZ z_ep_J-bdVQXHTr}nBd@ve<-MC58VYg=ZT=IM%nuz(}ZpC$TaKHg%fN&1A&mC$v*p(wKyJ10;n=*f<#aNibx&uq^m&HHVWGV1iA6&5`@^%L?_>;t{<=@t5WG@#^zZJ-+!LSEV_ z!5s5)QtTvyxhs`XcAp^kY*Qf5tuP;s>dJ6b?Y849PASYbPQu4w1`4Nr8o>5sDya`H zhwpFBF}_F(cx~7T86iU4S5ZS)@-vp|>H++xu7)#h1(Lr#51?-zvYd*?AM9XUp&RkK z5dHHTz8f&a_${pa?uumftxUvk{^-_PLX0Y3Vc)68Ahf-QmvOg=+_LWArKWX*x9B+f zRb8WHwYl_c^hLU!jzVYV1Qg`3*<06SG-7wJw<3$F&1ehD)3uC~+CkD6;CqevmJ8IUxgW2mWu{KPJ2+AEKoi)$l zUZ)@m2mwaBZNxFAA$##f78Z(M1kV{&L~ZR~#)12Waq}!tzA1@bE4c?TO9lA~`qiY1 zbs<|7f8a$UcMS4d&yjol8QYf~gE6&(zq6b3UtlcQJsX@N};X;qtrGr1CEhZN%Vmkrc$%T;Kf_ytpr_(Co7 z58N&g#aE{#;M%M}-FsS>>(h4{t0o#+06 z;;iNI@aYy0o^CLMtGrZ*c{~VZiErU*r96gP4P%noI32Sx!$8fw``&4>J z?;;17^7La6-M;8pin^tG)3v)Mk#+z4r4y(R2e|#`cP^#cpVQo8)JpF z2MxFrfQs^hFiA^_JXyDyan#p?WbhMAnLG;|WJ7q)?j2aC=!LvTyHVIrj;aJC;q9fL zsgCh72*s^X#_m+LmTa!wJO`%UWe%Pe#bi0oeBfFtLrZ}Ok2WfyR!ShX-8}&LDXus$ z@(06c1V_9ji7tJ?vMAzXxX8v454i7Q{Nu;4wLt{z@jcF~u1$V0tsA#Wnd1rF4*bDS zq#m7b!HZvk3r`lp2BjTj{vwwD{iO{q(Tr`HxU(n@^^DgU>C_!tovc(?MvAngudLZ=T6P$Tn0LwE>FnetzIKANE%FW%(AHh20XRhMVD(1URyn=5(l%TNb z0c5QMm`FR=jTPjN??PYwzkTuxlC(M2MuZGQ-HsI--6~yC0 zH%h-uL+gxOsB1V*9kK%;`(_gOL@MzjZpP!HJC}(;&OeCzV~d-70Q{N_+0T$--Ihwy zDE1CQy1d9p1k3Opwg>I`_PA_80!p2|N=#fXfx$v^7#*nO#i_N!niS^ycryeZ+`Vw% zd<)KI&-HDNzrm|71`gLHBWLM%Vs^p@cYW5z`tLX4anlaCKDiYx#0XJ4qgHz4_Xq5q z97`wGN70QvOW?%ES!n!NfLr(@1s3qf$v?(RvMVovCC)=Q-)07#rP>R4QyNMh=)#!_ z6V&0B!fJjo=fJxEFj7civhPf zg0{5)SL^6zQpfhdn`XD8(`HZH-?;|K_EMZ_{(`eI)DKQ&O+`yFOUSYP#98+$?iS?RmPgWKvsrhF=X#g>cqrw6Igj-H&yfSfJg^>G8}h-I2TVrRe?whSP~DbeHVd;v@$*!P(v$MJ~p;T zk@NB?*!#Ey1r^XU<$7H8bR4#4@~B}663jz7?ExTn4465y}jWVe06^e8gTZZnGSR)%T9OX%h~p?J`IJ8_S^O+7dC z!^K^V5O+HnR(cMBpCkvoPZz=}cg6?IPNQanrpeEYGV$@_A@FH#z-cXu@Cj!t-5fj_ zZa@J&Y2}84>ucx=>n}hV*KWRVEW`*efj4)W@v8O@+@)0r&8BtgFO)u^hBaP)A1>5Bz%F zo1C^cfY}*ER3fMuqH8Vbj+uf`<&g)64E*TLE|!B(o=!4yZ;*LA45{qY0Xl`I6FI}@ zxcIyi+DX|H^)^+gNYjG_l0y6)W$WO-rfo1mc?+~X&c-H@c6e4CPNq(*gKgUT;D&Jm zsq!rZjkJsSJu(#1YK8fybl>1N{bDHDwHdu^qjCQ^O83e(W5&S%nDgf^_&B@4!Feg5 z&1S=%*)7m|(VP5irTOQT^aCR@&f4VEpX@|>-S|Q z!7G^&-27e|CjA@+>BU97=!6@P9;t_)Qg*?w&nMWdd=(fv57C<@PjN}tA3S?16hfEz zz_Ec}sC?Rpnq4fR7hL|~2w6<4s@34=a678rD?znY%`kqU7pqccz=pkjBu!%pmN^;H z{)#w=4SEDO3(V>5L>`^__#+9C5v3AhXUPZIY|I+@hg*JiW4LoMn(kVHQyeGb;P@y= zV>4M&8SnDuv# z;o0P)bnfpyITQop=F~o=&iFGRfL53izZ5e{PAyicFtnFxT%Xw{h^BMdj;dzd9AX`SR1&gE z1x$KaCQ82^?`^S$t|RPzbbAf1W4re`UgN+Ca>Xh3ji{9`4=XONz|x6fEUz1e{hFVs zMT{lJ&kZEHcZBhd*msl(946hnk~!|VrugT1Jg#x#({Rc<3UHI7~WxT*xkXP zKkF^+_@#wwM5^gQt#SC=!NJ)o*U<6VLr`2}0aqOEqkDV;J&?NxrKZ2Z$+hS4*Kj1J z!(;Rqn~J-BxS-Y^#`@i}kY-(32M)K#alPv`V)8HxOO;ka-l8-%H#kUN=iDTIjT`Z{ zUoVM@%0`^=hgOQ!(xvwS&m8@Wf8rIBQ~wlTL){qU{4}N!>Ob+^)_A(J_zC_H%Onb4 z5@2NKTF$AV9LB&pi#L`D@E4?YL1(H9%Pr0RDdOu4@VkHpU-HxCrT)-J}(Eeylgw=2N)cmc7wZAPbR%x1*< zW^#N_2&(staRiErAwg^^n}rOb{k2K(aN!fIlwqGwKaSCCudBq?w-hG!E7MKTfwnjO z;n!&$T%6tmvvupKIC`L#rXb8@KEukVLR_u13@Sav1SQh0!j%h~penB!E}r&7zkWH+ z@5lP6+^z+86lUSq%87WndR;Pq%`51CH-%@oxgKs0mnY}5yS`5MY#fM{AjK>T?_)Ka zoY|FykG4$5o{6C-TwDb6MJD3f_f9Ztb~Bn!bEKV-N?_92qVOe z^YMFhuGtQsjQ#PI)Dv{<`heLb3+ObCI&>|c3#C$}kRrmzLF0N@KM+BVRW@Ngw-JWp zt^jvc224v^gC~do;+dT$)SJ%7!Y99A_W3a6%sURp^jcv&BZYkYnFMw(FOpe`E|{p3 zfhW6H<9X9koFFGhZ(bY(N2jlF>}@3R*|;0`sa4~@DKfC$QwBy7kvV@9P;A;q(0rDP zlH$F1cv=7$ZHz({mK~ik#}g`-3d5vfYnUhS6XwhHLXv7WnjU=18)JK+AEw#p(}S=80GeHjCu3{Ez@Y zq&pr*HKy_k*STQcD)vf9f3l9OS*5$tS;HQaKbre>?t#eW~Gi)@~Q4pC0GzlPScPKiF(urVH!GT=C_6 zip$kS@lmcXp?1r_bIoy_rtXf@tIOzn-%8BW|4DMXH$l*`aO8fD!{et-;gM+%^1Vz^ z61ZSCrwFoTx5Bg?b{^D3m+UN3s5%DIcPnGvS$(>6*(&_Gs~xS@ zT436k6V77&2|nA6B#X*p;M!gsH1J{hKp%AJ2|)$#op|hsGcGNR0*S44Xjv!3??`B* zH`ROTw3BBr`_vHVhqb_($!=85{wTzTAK~avUI0Pw&%=G2Kxj-6!OZs|khJL%E!1oV zxh0!8f)736?=BvVKJpxeF6_sX*V4ex;u0)~xlR*=b%382i_2$E#IdjasKNZmWsU?U zOt{OV;id_MH(rgN8@fOxEd)N4yo9IMd^t<^B%yHX4=g`29bT=m#usBr zq(fl`8k8>QxHY?S3oD|SKj^fud$)BKC%8BW)K*Y5 zE4hH*qXhV&a+Xvu&lYNP!Z2dc91IWSz$JkRTyE1+eEZ#zu8Xy$)jCr#*RdMwC(nn= z2Kz{$yDfSc#ev+75QWA0F(9D#26a*l&~-}`Dh5Zu$`%VKz8gf#-H$@gq9D5c-YAeD z#&EeBPYOM1@F1rQr}tan>whKmuaO6wJ3NNXgYDpY<^n8@%z#5G0$k;g4qU}{9@QC3 zVW*iA(egECS$$WKymc6D)~Mmlds=Wx_Y6wgGm^1x5Xz-HVD;aA5^f>LOFzQr}<2UmRjJRyaya={9 zoi_rU_egP?F$k^hLzguE>FX<+y(rF$j#kdynAv?{aX_?<5@BK8B*UZP;gsM5|Aj|0J;sJgcvxf#W+&q&#ZAQi#7)qKC@g zc82nJQ}`sPiEA4JsaL-MH`sI)`aY`#r8*y6dtfOhG_2*Qe7A-JY~S|t(K0Hgb`Vx? z6b3=-LB{8N2TBFOs)Y_U|q4RSYen?)3?Hrz|9+AT39=@;tc?g5RYf2i>( z9QNAhLEZv{>UlQwAbWo_nXDrBHv8d@vjZ%XBY*;(%m;F25cW3-Fy3J{{MI(4*Jal5 z_IBD5ap~`v_W3g8JDSruOC4c%%>_{Z@Cn3!xj~FgH48no!|Bg~FR?xF= zBW`*Xi}rWrh~zq1XnAi&xgH16W1k1+=!`)|^)-@jUjqi3cggzp1Gpq02(2qK@v{|k z1xhh~sn%^MOxp-1kE1y;z8^`{l5fXr`gn0I%P+l1pvlW1gBMlG1zy9LRZoaXqRil z*FH|DbZV3nx-b~`Dl`Kmo`Yr$=I^q5jxw?;Fp2H5e52pOyu+iIeS<|oMxG8%ma$ zl5d~eq3TaN?DvSlMIvF)9Bz%KbL27eZ$8Xp41r~3cUaal0xjjr&~k$z8a*@s0hw&{ zR5=W$!aq=F6~#Pf33#)5F1S>xqhG5VsBalXL&*+2J;#+ys8K|&v=8v<82DvBBL|xX zF*>3SbGebcJ5Iv<@bc^AYZ#aMPHTqqoTVW1=^eVOyhMq;tOItY77DC}Ve4QM$iKE{ z+2u&y*3nQorWun;S7N;Kt~D8zNyE!T;q6m z`d^^C|3R$w6kJj{1vJ@CY~%*ZCX^MT-aZpl7>=T|BiY^5GY}WlB%{+y_RL$uflpp{ zP*q_Wl-Ic8Ark>SIUx?KK2M^`g6SB1%Ne>tXM*Ii0CMe061n7ENn?)`;k=Zfj(Z2?^q9@v#NoknYaD>3k!PT;zG`ZPDfCgUxa7Xz9@KU^g+k*T6`MOPsKIg|n%5&ewUc74F3dUr9)#sxMFs^NpmP^_&Or4_0Z zNNs@uNRB(Aw3+}z!PIab?;L@Z4;p~lMB$nvG1ykn4^^xaxA(s-nCiX|Ug*sx&)@$* zTeqk9@qHS!e+Yu{X9%AcZ^g`IhcQOkj4nQQ554F0Q@*w+&Q}b^^}ox&T~3%U>XJzg zZuQ2v8(&Gz+cEgC{|VMStAd{|KH~kFG^qM6$X%gxjC!qGjl6z$_?vG4rHh(jvAHKT z)AT}ANe6zA6%?$CYt@?IR}u{=2+@`W34;?~2M@NXO)L>NoMqXBk_6+!Gf9t^Z^ z2ax&*Z+Dl1x^E}6%3$!&JD#`nnm~dqAwB0Fwox@QAb$^gd_%*wF8E zXJ;dw$$DzX-r6wFc@TYaOPGIXjR@J@6Nc5-7>oYXMtosJ)Py8i|`Oo6)QOVenDuIB1u<;ELBnaPa;;n98`#k6G43W2_s$Kh2}| zSBo)f-*2{WDhD-|4HDRB0g{%oD6`}NNLMb$DF+b0Tzv^Q7yPB&Kf+;YMJITy5aixV z^uSFPO|&s#FLu4S0ky$DzD$6(intv2+UqXDgu(yok}Uv2q=8}`+a_R9cJEl z_Fn6G?wi_7?tsbryXdICFGtOBkh5Y?=09Erf@aU^aAi*;GM>Yy`ul{q!>7okw zs}f1anoGB;nm9RC{5&CkUp zYt-QEFG2pkvvV;etPaXEQ(&`xC}^4$aZc#-Nd1Ldc<9SGZDX0?M+YUrG;17tSvK2{ z$0q;%v2gHF4$pem6%e{TkD5%M0Rj1WaO!h9#*|%!9sYN*+X} zIN4nU^)_Ane`cGQdH;m6CP4^HuSe%wmteZ5DCW4wgWsBK;74=dM6Nb=Oc5b>PiH8{ z^P1RQAs=P82-1tYOmMl*I7n>;(7G3ft1|@nY|RDH@;&(Vs|7WA(#$(~t_n`13iB^# zeL`5}gE4DW;gH%GDD8@ae-BL{=;}huJz2x%o{S5#Dv$o*tKo2QB&^@@5;wJ+i*Q!B!%-c{yls3(1Vc6Og*=F{Dm&!GKO(wEWuw{pRdDm(`3*_8Fp&rxEZ5 z-;--!9dYs_c8`isCiRUvu%y--GcO%r>>pFO?`(-u;wgB%zZO?%)!^J)+7QjLhGl^Y zxJ%XyQg7UXpUb|%pIJB1Q-2AZ_Gm|^STp8Q3u^x@7!PKAN4j!jo<$|JVhu4t7GsR!8&+nv4#QEnwlL-FSFM zhtk972n==|q$elEz%eUVT%VW%+Ts&2ES6>Cui4>(*14>QqXLH|x$tR+Fux(l4R=iO z=eZ`Xhwr&hVe=LR)K)x)TZSe=)8Q{@EcpQ^R7F9+OmjMoqlo^GddZLx%eD1&LXx}_ zqTf_BCQ#>j7bmMM=b$BMhESQgL&`zs2dF1Q!#?q$&(Z~0hQ^8h9veGbM zjIG(WtXu2`jk@1)NoqCRadUwgkF&t?*<&2eW(=aMO{8z{QWUNl!XFB+p~reN?P_#E zo9$d8ox2+}9@Jq>NFe$T#-Q7Te~>WuGwv6&!}CX9;rOrzXsJ8OVL-7Xu?th!Ej{1h8Us$f~ZxxYJ z&Zm0gD!9JXmU@LAgxz;<(4{GYa6EQ8IPK$6*NN4b(1e`#>?|jq|Aq+JdxEnN;)0%~ zIGOPl&p#T(vX~IY1c+fZ3SVj=a}PDg&yd$OHc;y@0($YU;EJg>+_`N=^q$y2NjBRB z=a}F|HwVt*ttwz;FAQr$S7Wip5OnJP;(56VL4*AZTo5`;H=h*-gSIg8@}f9g8Y;ji zie*@K$`D>_50We`CsL<5%-Je7mGoyb_v6+a*sxa-`owDS)@dQ~#hft(ME`?i?_wf$ z-UXkyTEqMNCZ+`X4DClPbb4#))`ZJP)A3O334wVTtW*gig29ohMNUzP%rm8+&>`1 zKYpkhe+?Dku~o3!c5#AFP?(1AC)R(e+WA!OT1qipB~+U(l=uQt2sQswT^A*>D3+f?AY+}&j%TqAfYE5ojh{XpNz0fw{KX{cvp^7dhmtOCK zr_W39-85TFDe5Oqp}s7KwFe6qRpW474u04m$ernU7G_FylKOAo;96@W2zCnMveV1a zGp3i+wP@n4BP-FscwD*Mn7PpR{G={Q0{mi8HR5n`66^5fu^yW-G2MIz#1}NdgbQC7 zQ)e4~^xFW@$9|!Bx)8+aeuRY#Dtaw9ohM~qjAAkCiSop77#i&a$zta4e*GPDdv?>@ zMVXM2c>%UWM8eWj^-w;Q;Kz58BVDZ3gSBYN4(RgE#=9}jb)GFextU<(%UJYnLZcksp{4dX7Uz+(1m)e+@R zC95cSiz>3-$~%N<3t*4YRWzBC2>X>?Am4N~&w!m%cIR}HJHf@!(Cz`EeTBd^-3{HI zQ=si{A#PmD94ae#oVpW%U=*2v}Y=!RC=- zh+`S!n#327<{b>qtllH@C4lU^{~9#s%))D*H0RQlG=HAV@LT)b1r?OJY*sQynWx^KY%th@Gc32q=w?)G{-9I>uacr7}$MHha z3p};k9frMAaKa>a(h^q-L+lK;eKa34*lfs|?Y*k!O2FI!D_*eC0is~=Q7J@UfGZb% z0wquL!D+7-m90wR>=db>6D88&#g8=9>M=vtv;ef#nTUqTsc>bj3l7}*hAKuv+`{#q z5TO4FRCEn!)KDjc)G&|D9ZfQO-%6N%Ux2@>*PZ6Q6CuwgoMhd0c4sfPgbam#GHK6F zSoDwOCI2qR(PmxvvCsf5zUN`;!u@Rfmq#*6DwWO)WS~;|CEVvQh9*Lbu~5&EW{>TM z$~F5ScY`Io4gH8&e}woQRWE2Dxk}zwohM%09Ux;E0IJ_gp;%^&O!?A;??9NS-g5`H zZ^e*TV^1HiR)m_)@?ADGK;7DPzSi%XTquLExdhCz7Vd5807lu()}+x>7D1-iObqX zNI$R?YO{MG$*&o_CJEpl8(%c465vmFEQF$!W}r6r7A;d~#X_xNSn@9#&5CTW%I`Op ztUCf0gEzpobPOa;6_aa0zrn9`HFWBQpq9l15H!sq8ON4lP+Kjo-5rTS+oQlaKn^nE zN{RT4om7^&wYowVP`=(c@q3j?;&g|osfZTxKLnD%R#h@#rU+lQq7~?-D=>6BiIl(` z?8p(|j#Ttx@DxXQ)ASmB-j>0&9jj4~eGd(u*V72@FHqSPfq7%K^pamY+{B!4s!-=+E_Gedl7HOSA=^s*;4H_-4`}ww9i<<-p}a zTky1#LO;i|S#Xu{sslY6(V*#EH|1F>;XlK)CZ`@~yO$7SM0t z5SGMdoc?H(5C-+?62$*f3NCH>g8`G~!j1P$uw!uvZFNkC0$E``@0}TJ@;HL^drwh? zcvalcSi2^jQ4uwyFb*OUgDEe&Nk7K5jU`Vl?ERM+|*V=R7VT2~MZk5HEYzJNF zErm@PPe7+?CQMQC;aOfVga2xnqw(ck+{isi)wfn*s(A+3ES!W^Dp8oJ?MBWYFXQP% zyeCcn`a$Cb2Ruf)aE1O1BEHQKEB24W)xH9JcXOO0QdJFByY*r4(i;fq-wHj0UHHT_ z8%3@Sq4q4q{g=-XDJ3_MpC-V~+noy9W@#v{AVBA@RK!9K<7|Iq=Zu$y%r6j!gK3VC z)q5B;weqO1P!ip?(hGQt;$do|Cpb3rphM>f^I3PHmZ=badvyR5SG~kw$KQ}r7!MDJ za^UJ~ilx()!F19zkgs4ITs<>oPw^N;e<`>&tDE>pnqYO3Bj@;%OpG##hE2Q#(saKV zRyE$kZGM7$>)1}xlOxE#(#N=6`Ih+nIyMDfGM zTFjkMos{w|1g^(!hBub+JRz+gsARkY$NIjb+J<>xFhdk0J_gbQ?<{#T=PW^gLNB=; z!9j&7cX*9M4-=gVNn#S7>Gt`|2k8@3%LcXLC~b-RZdW-yGOB7=q)x6#Dk(6jFb)8x$|C zgcUnl(BbGR?EBk-kDSXWhSACrDbdhdA9l2%TTX@T_+}ZoYaBN;vzmCqx6~R%_v$ zrum=}G8sx(mTrM&21>5k1Q$XX>s@>*s3uC$=V$K{Om+rg*AsALa}LyB7R9zv4S-md z>0Y5gS7`XcnVC))qr4r?Xq^XrWj0IGU^Dx!L9|hFCI{9iL5{Z%+V7o#;vUxMbzuT& zU6BXHCtKjB=4@Pf-j&Qr$)F`$_rnhJ256pe4l>VYVV>PCG)gYVSw~J2i4kw;)f&f2 zc5Z79-VZmnmZIv?C~y>>&d&2=Nq(nCah9-SuDs-E#y7F}p%xA+9>+yd?`g8~Y>@V< zM%CGJ;59G-)+zSk9j|hz_V5PUZ%t;uY+(76MAD&9P2x8igZ$xUbcme+D`H(iNvwv- zPFMi9cc!61odk|8=%Lo)e{gfL4Y&%FVM5?@P?KP}Ri(4EB~TBF2H(Pfb|HCtBan`M z3xHPzQ^|Rs$9R8bKdf!p0}oy;2E8ZwRQIh8=gc`jh@IwvA9tw-qcCKZ$xy zUq(xY`)Cm{z(WoFkU3!#p?U@`XD)%WE0ZBvBNOHC3SpVAF#qQsN2>9V{a%C*vc0lC z-hUgXDA(+ax(+3m%s&A^6}SF9$o3_$FhXoC^xML#Abit zEt=N}%{e@LPuXYDJ%LjiosMhoe4xVLgUFX^LH^8@LC~cn$hWcUaHY~d%1Et%~Le3Q-%&GLl z^`T!tV$2dWQUIz&3{kHKAi2DPeO{x~WsvQX4nCo7rM_fCZa3Lyu$QBf=78yoZ9t^Z zm|7cchIO~z@!Z({Ug($@;e^D41pS7U-^cLCfeUE!z6QRDtALw*Gd{GF!_44#u-!Wm z4Xz!Xb6cu3gJuh@Q=kSa#Gg}?Q8`38u=3NJ#T<<5n|AZ zeGc<}ec`nAn?Urf2hi}_oAc-IETF@IFn3c4{>;+`rO{PnUwbwUTuChi_VQ(UA3LFQ&*erHZP3lMIoC0RQd zrzOP{hX0>UnDP-CH5mWZUj^3P`$h`Hh53o>zG!==4Q}L*fakv?h`G=Yngx!aoZ5p| zS?1hfUj*}IeZ}1?lo%he3OaV!;D`gl<-jTkNb$q2a2quG)DXX`7xx>|%Q9sGptQ9~jBY$o=fUW+HAW3Wf0fmFUc0XwEzK-BDL%)9Qu zb}{u}+2D)*hbOX(co;k=dQSb8AA;zUBE}x_@a)Soi0e>e&-iBeoDqP<*Q4P>u_}m}m{Zkw zO`LtXpX>~phTY+EXusw-wG2ssqHZ17TX!B8FZ}?SzXjm2N(y}Rs^ z0_rwq5!=JB@aFN~*sl-)6))Ri(t1;Ty*eZ*Rp|>nw|og!^0}a}M-uXbX#B8!Tz4&l`NmJhGKgC7rfrg&LFpwG2w*;{7y~6H_1`> zg0~jcW(^W+*Uu>6YleH846%DDV|l+?jh?OlaL~Ax({L=9mh0wYqd^NQFptvox<8yf zUZMCw-voAL`Qh^Xd<=6?BXU24Sf6DwIneSBKhDX*MPXM#9MvHpSsw2t2=H~Lo`)m< zMmVlxAMn)AeJHwN1K6k5K=5pDJZ;koA623`qwAbGpKE@@n$`}>%R|Ag;sto9KBSYh?|{b}6;fttO{rcK zhj&PbTXXiI^5gPha%uZ_e7(5|YzLC@c}Wx2upQ-Ng}+nQ@U`1w&zZKOJ^n z4|^`Yzzvem;CVndT6_vfDr@vblTm5R730D*voKJaVT9&CV(I1! z9Eel|a~Fz>TTj6Y^UwIW_c;bHFd#>q8M|NV7D_~!fNHxcRDQ0)fUsJc?Yjt`D-Y7r z0}(|0suy}JWj*D&nINqk4{Lr~L6T1lg#VmPXh9<}^KZld^Xr?F!f~m55|wt3#hd_1 z#8wUXsBB03+g^f?4dV@6VHv$e+h9^ZyJr{sQl~FwkVU*9F!eef7PW%!OWW8E)f6lF z`q+}GN6w44p-oXO+zYp(Pn((($IldCS7rgOpFE1!+!|rJRt{OS2gnsHBUcU5*eR zC9i;H%{vfRj|S^#6Cmq5IA6{WgF)68xb6EC|7iQ*1y2{c_Jk?#`J|I+B;eeKY^N(j$Q^oF5% z&+)?96S!kOa~xcu&*ua(V;XpQCg3C2-_Q|f4L9aIq5acT@q3APQpAQ| zP+};E@63OZc(n{TAbkdf-c?~a^AxzNQ|!_aAyRS$Xr?j==+;cU7rv0BRWon=p=t1t zWm*kan$YEA@9;)KAQ5vcptD7#(9<@XxBg2CtRK$B0}uXz>*ao2cu5zQO&Npkb*ktP z77TY@c|z#|anKKugT^8z{n2-)v%rf)>wknjSEJEB)DQBeyu~zeGe|ReOD&tOCncnf zfZQ=v43D#;W*^f~Px}qyA74d{v{JY>Edb-JK0~VbYvO%00#)}8!na-8@YX#QmuOz% zsE?(Q_Dtp+JogRe=B?u#+;Ru?v-43twH{N-Bxzi^sYjbF20pu}qjo<#i&xb`ZG za38k7l5%}ax*SDbed^&&{qHZC`#YK36L>{s$PXxVOCY;N{t1l))dC@RBB@pJ8Rm4B*e4(T`7j8tR(={^-&|!ZD7+iW!9cvum`JPJHV0(;A zp0yEsujinH(+HYdkKuAQhm(x6K_cz}K~r0aaDNDnD5bI4Q7GO&HilpH#Zl~2J|0oYoEFXVgWdARaP06D6gvNeOuxK? zPTF38u~R?Mk@YgzYyJgN|CQs4C2Me7lr2`VY?(w`A!LpS^Q8|eqKl&s-BXc7ZB2eE z*KJSXJz?C#!!I1rf88W9V^$cbzM%BuxlZ2Bm5yYeScG!p%?{XXI*Lj~HR$??IbF}^ zgZJ$-ByZ#}x|+t}52MNC_PJ^J{?Tk$FJBKOm$zc*U<*lJB?L?BqCscsKJ3XeBz(sS zwY^pWre$DMund-1sX^F-M2^--EgBh}L!&5!oX9-VWT=B0{y#xE&>ybE1W-kflhD=X zjt!b+xYbbtr6k^>f?Fv1tGbb+w!JicoeTUjpA8`|!Z7R78=Uh;gC4st39_yNteeOO zj|eST*L)ilPWFPt{4N~Rj)AG)s^IPx4d~-e!z1Vbnmg@TZ`4b9CVqnEn?YnuAQ##q zC=^Neb1dZi!G41XNzk@{V)=fuMP)4vD=@xY*9;V8vq;PEAJDxF@IxuwN`jO#IUcL@dHo{z) zlL6q^6@h!~no#@Ha=2i@9`tLfx_r#XS+t?>NoRt&3Kgl)riZx4A8sa@INBXoBKMR8eG*Cf|LKr zz?nl~a8>&!z8PZqUbSF|%#Opq%?{AjsgBds`1JUnCdjdh8ol99oZw8o!A1 z14pu%!-L??i}2RwAFOd(3E7(dG;-wwc%&!@MsFXmoOvW1x$Xe}#I_+PF#*nn9|eyI zjN$(GIBxqe4WHD#gJUIi=wCINw{W-`!r7keu;eW4U3&=2b~wQHR6#OPFaezv@4+Qm z#@ZhK42RZA;rvN9_+2;~YSXJgbZ!;hH_ZyNi*a4b zlzwZl4!P4CxYfM|MGWJiWNR=ve$i4{h%W&XwQA97o*3O;*i2V9yMTMTFLt~90Y#Qs zJT|8hr43>rA+;4l#3tZ#Hn&LK83(@(c7VqH3i_bT4~w>UqRGM`n!MpAzQ4-&3u+ZO zK0Op~KDFoU3^M?Gn>o1VL4|UH85dU=GKZzh2<+E>f)$VAP{S*iQun{monwJ_(^XLZ z3d?RMeI`k3-r%Ctx43KPBAOZM4wp5T(QOCfc|6N9obfpqrv7a}k7?|ElbVTlqph)2 zx)(eAy0Pvoa{(lng7R8xoYF7A4brnf+fB|Gyle!|U0^)8!ml`7^%=DTOgOJZK9PEs zVc-4y3dwieh1p>haNk^#x9I@ILb)MKJI?&5TSJxU$#P8Ak0D00HelhaNhE&5S+YmW z4HEktpv-=huACQ-reB*N;My=M4g`^-vv%TWM<2cF?}^^r)xedV4$@-cFr`_Fny(Lp z@JH6DT9}H?6_QvY5{9q-R)Yp_1;{`Zw9j3SpN^LU8B0SiMOCWhwuD$OK8=4b|3lyI zL3sJ45iVL$SoCEFbd>eMEQLnmBo&DBv)MxE*dyE9EDzcHb_1dz0~+X1-+elOu5T!ec6yFUSw9 zvjf@J9&p${3`H+!!iu90VV@lr=gjv72*7^Jlv~8 zan|fj9I?P2OxWJT`p_$Ja_|9^m&wKTv3l^{L5RPzL4&kam(Zdw31~lOl*a&{ynA^L zcdTCk>h}R>0rn02KRIj3sGfXlNFWdz1vQ?c5pY>>UK=QwH&zF^t7w@H82P z?cr-_*O}FLn|aloNk3HgS`oR4b?BSKKzbs>C~veLN^4W0XC8AdPtBpLj!uJ@9;R?8 z%K_{<3hBTt9p1G?hMe_Ra?pNeDKGYZ8HYbT4;Fm3rNeA~m;Ox{wxooRA=dxy*Bi#l z+5&v276IYHg4{Y@9i15H4%}sB90^Q@+1n@J+0H?Z)vG#4nPmW4)AjL8_it>Un*tB6 zzJ!ab45*;fdz8Jq2O&BA-wZr6&*H$pt+++78XT){fY>nsZcM}skaHEJC-3sW`;av;Z*n6X zc|?iS21x%Thh4J~!s^O#=;6!|grreOU@;NvM-lS%+%r||?l1#nVgR%3xNj&RNi$x2el7|Jn zxVi$q|NIFVB{#rhzB!~`%jH!YlyKDIFQ761KN$GiM>VA05#H&mxL3*x#VsqLY^EFL zTg|5iliHypCY;s=H{d3YOS z)$ilVRV+`K%YzxXXD-#CDtGSnckuHr3hAqtt!G3NXsOVir+Y9D6t~5x`{r8fblTau9 z$0IR)O&v_IZ|99VUPURLPH+lPVP~ADtSj^l?H*Vn*I^;$wfmFKwLzSM^~aI^{6)RT z|I)f9IqLQ>4gW@)!CI4OUY5mcQfbE+l;)K%HpX`U&$gleQHnmp-FPbD2)Hfu!1{ol zaCK!qF8giG7%jrMc#ApqHuRGfQmGu#a>jHG-bX@4kiKW%Jg7S; zA2J5p8GmbQ-Ev$s^bfXWJL7CwC!&+l4=28I-8 z#_=M{?Si3Vau7aL?WH$_p5cY;m?X7D(Qvt8B{aP%f+d$f!?HdbIN1M^{F%gq-kW8( zz^M})AF^HTE-o(LoB|o!1^62nd#d%2IhII$#Y`hL%xtg54{`q3;OT}I`6bY`d<@+t z{oquOO+#5xmVI|^hr0b9*fzlUY88*%o1JkkZXgHw~Hnv_wLysOj=GTnR{;L9?zh-dh5D!$HBVpg>dc6Nt4xAc) z!sma5Fq+tfU;7`Ew$xr&)St|H4i3tzD&?>)ypa42xIk3@D<}EVUm&W*7|$q|(iYca zpmt>d+88HArQsHKoDfF$YkNW6Ly)v2&x0=0RP14&1=lPIl@}bunJo_F=9+K#;`bz6 z{v{dj-5iJB%N=-UR0JMAxJTWqgYgIJ9=>^ZhF3G34MH*}@vKn_F`XdH|D)=S7Jq)B z5z9FZJlF^|GnDY#f-Wi?(2pw5_QJX!A+YY(a`3mGO*860VCVb=V0}r5+=~u|5K$4X zakmwXKW9l!F6l(WZXv$M+Fy`AuMT1=t|iUfVoyd_r(&oEb79GD2Ft^zL8jS~(-rd* zHmCf8V~uVY?5#~5?Ok}9G2<|HWfFc$49A&r-yv<|~-{|BUQ_7Wt9a-^ztA=V49e>YkL^;y1ksCSH9 zZ~s67T#A&P*5}a+(rNJb*#dZ|T!)rF8o|luKAg3>2in>dSg-mQ2j7TbSQ>i=xV}aW zHp5)3aD&cX+Jn9IqquE#Oj0A8JzZLaaKW(*SE_}R)Qcln!FsEM`X^xTk+1Z9eKC5j ztAvod=D1fZoF_k%i|^wfC}$u2O{SdnfXBN_&}1YF-8aVJz{FhAHnIU4jyhoE?r*r5 z`LJ(I_=B(4Ny5n;-59+>4o|GUg^_yhxng&L%c2y!(B-okL86-OkvA0(G%GOkG- zJDV|HmWvf+u4f#{h`(^(qmxWdm`$DMf5WX8c#u>S1kL^hM7sJDZ*PML=%Q|U8S5a}zq@`ZP<7C7)S1XKHldCx-<;bv z(wzo6L%k2%z5R&m?mSK%cP6Tieuq=fT%qm&2j!p62a#jUZ7?GP&n*i(-;^icwIJon%4Erk1yKI95z9nwLi6ib*3l5=Pg(wi z=vp5D=cjS-=Tnp-ztIBAkJm$wbRWKr`h@RGCV~7`F_+W)=%>cUgy@jiX{du}6z91&C z8t;lV!LXzsF*{{~k;o%;2^u&QJ%t9?QfQ7G#ZP{f@FrzD99U)r;?M+<$D+_svQ9bG zHjAunc*c4Qy+rc73}!mpV&rr)c(UUa=AP{YuWM`R%$gD!|0Wj#d^0g^%08kyZb>Jw z(Uw(}8`ex>*;g_4{&ocX@n?Wn?ve-%no;0(yBhEA&%kUIZD?bD^;V4!s4xB&->i*C zB~cTe^pFr&LQM)bdpV<4uN_HSEWmZSmqI+MOL@l^`!H|k7~W#fTW1b)JZoivOYd3O zBa(xL?|(q4hAJiw?En$JJhtUK^L+YV)8qR$f@kUzuwY#Rk56uRXzM#ze_aNYTXo6a zH5XyQ!-w!XeGLSv_`pv!cPjjzgU1caQ1~_Lg{Wz860c3`RzU@oYA9fLkxx1v$e+VRsVxnkpbk2vKh_8e5_Fa22fWD=~tRS!h>~f0{(-b zhyqwt@e>2Qv~a<21Ey^J0$lu!L+PGmN7zYFoU#?JzG}frN9I{|(}h`oI3#wV3hb^~ zgNM%i#G=V3VTV9EcGkK9@4XN=rz{f5Tsx@d%AgE8ySj!aVVCs}_`m0`zj!um^U;OE z)?Q+GLJdzm2nO56wPdgJ5Oic{!lEHJ9NexC5?kY7!LgZeDP1t`Rndf~k6Z#j<#$Uh6@XZxB^jp?|&mkB#J&>laLQQF# zt_ixClvB~`%8(AdM@FT9pz_YGokW(EZ+^3C;`sPqqW`@Bwy3uthtGKYCKKS*zfYVQ=M7OsrIUU${{&HN=CE^g z9^)&huy=_nC|-aa|Cvn;nP!LT~Vuj3G7MJcNOgt6;XdE9mEaz=@l=;GuR1 zG~O&%R>~fOd!DsupKyy4|LZvxeAAP00WA`KZ!Nj})e%yU&VrLl5s<|k zb!(ae@e0dea}r}gMY<6to^Qj?+KekG+lo6Mm{ZFe!rUdXIWT`q8rdCDjKat5XhQTK z()IQyUfw^Qv`zP?htv4*_D%?_@6N*S>s-i-E%|i4E)UF0gmJ=125hd8g!?S#q5sa7 zCwwsq8zbKlV=_#3E%8I2_m41p^f0W|>?6Id0rY%d7OJcqfbQrw9Kli%P?of!heKvy zh~;-E+pq&23}R@nY%}I+T0+gD2e5RF8OYu7f;k7r>B^xzIGmq?O73~EXq7X>*s(Lz z@KJm^5r&J;>I|+Z6MnimS5I%BQhi=QP zVd8^PkO*z%oxkNnvlIQn_NX*=8Sf@rm#;@j@lGf;_u%ZcQYQ;YH$KHj_ZzeV}cCr|~d?rU(w5bVy zq@M)AJq2{~Q#%~se^xdgKyrF%Ds~1&z%lDIIR7C7kA#MSmZA;bxpx?SR`_6HM;@zE zPRDn5S?+SiFs%J91Uo~`;H~9-+T?r@7qTqQ+;ZkN-BSQ>6)u9S91qFgLQd??eC91o zf*<0$;9N=%jBQbZ%KMw((UN_jEY9@c%Wh$-t~Q>N&w^INc5q^UE8BTbVd1GzxOY|* zM82F;AYI&3%IkQC&K zPCJbjZlkFDnQ>|jrjhZ_gLpZjA3}=Kh+JVVR`K1ScJCLsW8_SdyqDv_<#zZ?W*M$v zGvyocEH^RrC%iIS0k+TMIc|B3SAWbC9)16byKY$FRxxjsZVtwC4o3-R!iz(uP`GtI44r2ErnJLw`%oKv`+5VnJvm7(jCbOU ziv|$!DuTM3A4I81DU8Q^gU$@m#t)4R=pJ#LZV0J{z4sPFz-$HB>iq~WY<^Gl1${Ak z#{s-BauY6ZUxp9-R-@AaJ5ph155g(m&~(!al9Hl^!cnF$^Jp!n$oC1JRM!Dd>o`aV z$mJQ0{v-y^m^XAvI5lfkgTNDv$vE*FUGlVs)>yv8%#KMgb%hzEc-Ek-O&qxzyBl{b z>Bg+jjQRiCGfCL;C+fZ#fn_H?gY=>?5L*5PT{ww&d9?ulM@lA-voR3#F3yJucQ<15 z=1~Yvdqb2CeZt4paTxKym70xN^K=e;#pgPntk=DZ^HQab%(p3r&34YjAjbq6^fDmF zV>7jX6%QKCU(vIcoo%m}U|~x-#AV#T3k#<}B!AM5q(q(2GL#_6$zh=@BTLFo4BL z@0Bg52k`E!E`dn>oirh+1^t?zqf<@-nl8PHpXYwZwJK~06#0s5pXLCPDQlp^n839X zVIJ>#86?C@p@yL`4XhCcqe2gC6q*C(nu7eE$=A`lzz~Xk*f%3a3Ux$UQMxV^hR>RT z!ZS4-;2k1SHcJ?z@&&Z1u`}3OPuN@i6?}bU@sAJ>tv{IKij+3wdvu|K-6EJ>XpW{f zb&!5tkUx=SmpE$uFk$Id^s5l$J_*ambm>=+q-jRa*$Hzc43*&6_XjZRy)V&SRtpN7 z1-N~pLfo%MAL7pFsjxjVkd8lm%DXD_7w>Ug$dQ30yjdHA;L88R`sW8(#Qu)80fPaENlq|abEJrV_F?Lg;_7QOZ{p6LDO z2T;!LsZBeTMT57Y%9nU-T=@$x%gx18rtiVMAr^HiUyyAcH5g$yL_#k6!Mmp+cxhS> zQCayOTFPZn0QNgnTvBCny;tw7uB;Ct#2>c~LlI(! z9gGF!>|}>W69*yoXB$W`W)WQ-1ZqYPLDl*lXH%Fk{%UT-EzXt@wZoocoIM3^De|DF zw;gZr#z_66GPLs?!sbqAlIiCPt6YDehixJJ>JCI>Gv#`WfAh4adSjJ zkKwrSTl_xz0{VA)LmA5&2FhhZ)`&UoZ!_l2KUTv_9{!HYnJ>q+;T`-KD1%Lz6|m)8 z7|wt8OS%5RXGs1OOe^1dc)Zk+ zns&T`CCNq*|DQVsCncbE(kj#*UIsH$^;lMF6a;FLfxjsY59qTys!$bv;OxM7X#=Pf z*$Bbet@KeXA3jGqLZSL{%)egATO>IPo?U3gE@2y?@`#|BfwWJ9)Z~GCbE_tn#Jt9=nT`R zq}*HxSSf?~xj&#!Vn1%*F2wIUpA0KHB02I0F2T6E21vV{0lj%e;P_w=j#V|nyoJ^9 zY`QStWmg}0tY!-9LISY%(`*R(9skU8NC$ef5-#rPs_0? zaV|OiFAiF|=77=82;PZ#AL$O^BG?+zPv`Wf!lUzo{7D5q_?z{ZlSU2@N6DM8iM==1 zgbMK8Pb%{6&Upq(`XR9U)KPlwiyv)d&+Yqx>1bOOL)`!VrlPW~9JTrRBz}@MrfQvp z^jpVJ_<#poU%#LDg-N5LNj$24eTvO~ZK$!3`PW|xajOe`z)STc-enN5ZC0O=v(<~F z96L<Qb+cC3w#a7UmIeVhd);CtHRO$ zLP7hX6vjKaqEU-3RPrI+_hf{)IkA~P-XE7mh(k!%JJyw#3YRBz!T;86I4P1wZeNUn z1*#z+Pfex8Bu%w3@Z7*KojAicAF<@n5+uwqN2cKbJ7uE=7*Y+ z1+SBhxbZ#b!PMs?`2QZEYi20mg3a|fXvR9v;wU$(&;(6|F9TP%gl6_LzC&3ly^^a4 zN9B(rZ+<>HxUm_3aWlPXR|V(&JaKzj0ywSq!BNH_(MuXd?J2)-wU{MDvm8?M>3>iz zR{@1n{1`K*0|(UI@nqEms_xH2JaU42vFRJiceFt17{7vvlmZGat|R-?`4pzb2y%BT z=)w5cU-&zE3#42gq_L$+ zNzPa)AGWtL&xxNPddXPfkGNv4!kkF7tWSuUK`6;=U>#Rm*?G=%gmp&;F|;cJXmAEv zvrHP<*+$IP^Wjg)Z;!ejk$deOa*w;=L(S{3>GcutzBdJ1z~&PO^KjF%I17D>$ai062{=a$AYl8i{*Ik*MnFl z+p86Xp@DfD&ie6>TsfK#dmQd?`yZbLDSZ*BFs=ayUB*>*vEZ!U(F-$poj7<~gL5e2 z4M#BlIjOCeK$T{9ZlQ7#IFyvqo1gf2&GmKkaGDos8aIupaCOD~22Wrr>+rNYsl`># zi9k=yUaa6(gC~>Cp$!E&Gc-zJNfJeM4&$%RK79iAI;W)_V@x!@%@I{ zdTa62gJJSg%!O7S5aiK$(l~$Zd{p0g09`d?h)diE=hc37Y!rS0t*W{($?YgTaI6Yz zC10UbdOALJVXWVcozQZWf}m(EKCJqPGu+JO$FGQkRY5%7(~pEm<8Wvd`-SGR4(K}I z0|s~WAfny?!Gb{ zKlqn0?>cO2$w6(G1bE>*1~1#$8G7$E$w^@hw0D}^OM;5<^Q0RQ)b^u?1}9;M=MCg9 zPs1%2nGgN~pF+gWgQ&PVp3c0Z4Jyrt@c2D{qWsPc4gVa2_Bq3#R@w>aVh?B#2Ew?d z4A>?g1$pHtIKIjT-|Y;*RiWi@R4)_c4*h2N#W>ts*oBO~0wXRq+aTT}Fpiie}KD~W9OC<^ZxgT2Xr@IR|2 z%q!M{tE%#3D!zk2{WR_wjbYfCCWSFq@^R_!CTc4G2X|J)!qycb^r(;`W(PYFo@owQ zk$Fe{G~c405}!g( z;0PqFNIhipUhY@yIi9eH98yx0UdT z(Lab6j>WXt*%*1r9Oi3ifm%)<4t^Oz{?zX%w@rYG{w;(*U+rPZv;i8=c}v@ukHb_M z#x8P^CTE4((UkrJH0g!eC+3qlhgiI&$TCV5ozU8ni&@3qU{$e{+`sk{9=68g&PRIi zZ%7oczA}V|NoDYyuaL9m%Nu;oJb1^{fh9f^_=@Mwvc>yzdh>O$( z6dF{Y!wPQ)+8J{UNOs@w;_|AYuV7Be-!EtM-k=aD&(((EEQg;f*V)Vf~`LR z^$@@iixO!9!Z?61B{{4)Ti`nr3s#n@!=LRd>Kg_2v zqx>g%6c~b%+JmV7gpW7JBm(ZSf8rF=u77L1$Fn9IvAgmW3S9llHP?JaFP}V2qSeZX z+F%Mg^>{+sz7{kU`M_Pp=wbWTj*)`%SGlR5w8-2C`#|o;4A!Z;6sIx2_OPHbE%kK) zrIAorRJ@9wew+kqw!*mg&2Fqeu1h9s)kCMxcPjAc2AvbTm~mI_$(hq@(CKMDX6~+x zc`7xE|K*y4#PuAES-6RMi^gKQXbSXxXd&%Qw^3JY4oCYgKX2vjFy#GYn#Imvct!6m zZJRg^lNleb_p+eE9UEuZvu6}lMN(i0y8F;A0nbo4k(H zpXsEJcF*LLcU!=?unOJ!Gm3RPe4(rVRY$Ezq|mr~2hQ978RjhLAn_S0c*|ylQ{TjT zxMYCNs(eKXFYCjqJ6DiTunI-9uVIv;C+snr4_1D8SamWDzc1Q{dx$9=ne>aUiMN1| z!cjWn@d@jr)S-9vb}Tzo4t=Z4aLQh|9Rm zu~4Mk02bN&zzISeNsq*P2jgIJ{txhfuLO~W^`I_&5}x0=Oaug(N9LzcmrI!X0aCpyX}#Wj@G|@gpm34v{j7v|SeMb#>^QhM*BGreeNco~fzsmzWKo$M znD)oO(-K+iwirVVgOzY5E&-<5CE@cW!>~s2Has2Hz>)>BxS+@pjtUjg-y5vaW%%(CO){?zQ}Ta3ZQW+Z-AAkJotUkfQo?3wbME>f`|b3$ryH7*DDgfe=X`5%5< z_9CHtZLq~Qj^2?x#TB~$1DfRC!PMXV-1#N^3J(muNKo`cT&eY&^V6moqL&`PH2+J` zwcd)`_4qto^O}jq(?78u1-2jd`zpVy>ze%fd5rTEy#pRSVtJ`5ThKJ@K;}r{+>5zN zJywMwCpMI*1s0HdCoiB&K^tySxQnjx*3dZ`h-yIzaHnZI^P2HN!%7c2bhj2FC!HpH z$5U|DfeidHMGJdtpTKm+r``9kne+8DKX1*LA*hKLK#h_&N+?NSWt1k(4gUix^j-r> zm6PFcebi?RT2Ha%AS$*L1uf0tH2*MVsD7Ay;XWMe|3~s4o1utdIk7i-3~@8FFy~tx ztx3}2mR1B&#VJ$CQ6n9Yvy+33pY}rjDL+pCryyAU`3=l=z6e@XTGajXZ&38}CwoJT z>EpMXIqM(xLuzF^5w4jG<)5O!mgO{U6)uxY3TaeGF#v@A@bj*3=7Cs#9QY0vVEKqP z>t;Ox#|BDpIn#%t8OLh(*~3sSS&4Id9l+t&D_pnlJV$y~0TFn@`e8ieF-CtJ*K2h^ zt>|Ms*d~HcLe=31)Zy}DXVKKD6(lZep!eB8?6$AwZmL>~yYc}|XTBn-(m!b6aW{Ht zY6!IGl;G2|O)%|l7oHVi%=roc)ziDsK)K}9Y+lPi!lAdKhDDSCRkQF zfFghQpu3*~*eT~@Qnmzc+WHat1dM5Eff*6dF2fhc*3-Yw|HFF{U&yb5tAxXNhkwsa z!B*b}c=$|!R}<_>8&(VOf`bKk5;cXK5k>Y4J)jtwavn0KFG0aCi7Y2j7OOhB-=O}kTAzk)H& zQWS%oCDm}t?L6$gUV~d6vFvwe0Y3QN39i46<97W;^gm@4bg5S&3sKE5Q}A zQ%F8?Ft=nA%pe2|6Ym0RU4-IUk+?Q=7k7JTBpSEeKpoL!O#Jzi7TQ1OZaFgwzAAz| zgOUbR{8kGAib=T4ig}~G^WgJ38w_B4PFD#N461yCoE2j*)5U}gd^UowH@`xam=KA3 zmVwm|UdD{gSO@3#r^9mQ%~JO823?s6$X&A$lX+vXb+SLc_<0x(EMeTjb2>0Je?P{A ze}H|Pf!=P)B$kyjL^<`K?W`%B_z4rcSu`q9u{vYmY&%vv9`#{Z!*x zII2B&fbwvbtw}ZF&@&SlVw8iHbpsUkv=O-L4S&=o;I+RyN|+B}&>MAnE9NyAW*Os` z0~)w;{WNYK|0B|3e*&%^%R{*hO31Z8L+7(BZuQP-;Ie9hTiV9-QXL&sIrST!y1XGT zbtTBB)IR*PeGf`cI}Ay8C2*-&ynKj@Cp3S%0U3Ge#LC_V$s{G3tMZwgIR1~jMDqxS zmk7WC@#L6)$`@dLOCR#=gNf94Q;aZd0p$&hsdqO98atV%>E0UTys9NaJ+e%*&H#Pp z?SL&?p{ITmoICvsilzGTrlJx0%cWo#Xvv!a$BV{hf+VDmLV6A?xK3vQLy$G(^&lEM>gFo}K?5YH_-b4bz#e;-rRuFNFDIz}<^YIH!ff z8J5V#y4n4ByvqZ=o4()%dEUl)Yc-e|QcVg)zrwz>FgTjwjLSO9;f!k=)I6DvQN7(D z@$nACRct^sa7AHzKWt|+g8$w(T-Pi<+O3yJFRUjrFs5fn-aBdm;-TmT@e`>#dd@mm4pvi?kXD%%O?qGv%I3S&Rp@9YSYgueF0ROW>(>|EzZ zb^j#Mjy-+A4ReF=SN!|<% z-Q#dr_5)aG)M8}Z7;X9*BLC|^G1zvn42DQ6zAldf&D3|ePh}Vt_g%obg+s7}<-fL4 zEA(1wO@2c#UgerYK=Nxet~kvYt8d}hhXh<-Cy0F)w6S&j2HbVKRer>{fnWhU>jwCF zF{XofYiS~!Zn=uzbRU9?<_;JUs(|G-Z}Gar5>(z&fxgb3C{BLidHXs7o@uZ-^DPt) znPBDSKPaYbh($}HQ0T#F+?IJ5$Gn?xMbApS!WqHvy-66B^butrZ^i%k%}9dBC>&T8 zi~ECL!`WnUwo@;K@sFQqz4;xYzM~UeEF!>-c;U|wITCYh2{`kY!~6jq7;lS*Sn!W& zmd!?O;kUSCtegBDWch$|aPZn~V zBdF5ZAr5(04&@6|>5hJNyzPFA99Y!>@5e+S(NU0mIl3No`YxcV(K?}X9Y zy+K^el{yJpV$AhX?(DyTV9sX`@rUHeLEa&JEXq88-KROC@~#|?z&}i#lmx*ai^)d5 zF+3DL3RMLGWR)*JRSxZgHPXT0mYe`O$HQo1-#@&gkp^`tSQ_J-IO zMIh8x579^C@!HRYq_0*!#%Nvq>kGZyj+$o3$$f-+Zc|{vmfu{Dh_lf0Yc3}` z*n|0+G;#AKex7sr2v(Pvps;BU<9&MKtZQ3gJoOFY0|6?;W?6IlN01bE3-6ydfbH8J zV9GCNdhj#{PYgbS)ChOH-{u0@8^S^O^c0TEr}>0`;b*c}w+6D6=3>z1*_bqmpC=(( zjlY+BF z;NuC(_`w||L50z-yKr>E1BT-o;Y-*d)U3INw?9-c{)jX4$@g*owp-%T$T~>ZjHREq zCPK;9HZaIGfV_2S7;88c_)?lcPnbgz$J#j>jW0NZ`~2j0Oy}dxzWfbYvL4mXwL;CE zUBDWU;e%KirrfH>wOk9-dCT;eo_KEY%Lu5qWWC}{e;ADQ0p~;Q#DC@ul4(!}*1i!a zBG*PL%Np^{1~C-UdxL1tv?nZ<0Kt~en-Yf!p`lWHBK@%j+nnmuvD8TkNpYY3^ z5!}7d6|Y^K1z{~woNZGE&}rdESUPNrHYd&k*_;H{K|X9>xBz$uq+oe|D;VGS3lpdn7B<6Am^=U-$ESEUDHC@srsSq+Gx}|a z!i1b7X+{hY4sVA`dRCNMr~q0u8)%ndDTw*{#LV>B0V0bkutt=9m+Ld( zbC*fK#prh~;ooXX- z$@@XL9L=vVCO;F+oF?GvgJ*E>PaZc}ZXEW`zl{Pjyy*2cgK+zs6_l-4gqYd{>~;Tz zdyeqXb-^LJC#itUwCDnbs~fTH*jt#TBB1a^eH4%ChETB|fnZco17EIn(>Gyr;9Amk z8o%u=Q4Fz&j@S7X9d>vTj=rnG`Es@Rs>=o?u5&Dgv~tXn6GbH*ECk=_z=CA}J-h7Mp-jv5u{cZGf5`4yg7Fm3wrE$Z%+0H5cJ zQG-X>$U2t@m))xr@f)$f_?5W6@+JHq7SToT?$g%kG5BR?Gw@H8!Dze-Runzt7@7UW zN8-cyl(J44!Q&8J>x&CjnmIS7JL9n@?r`eb4P0l=dg~`VVY4zn?`4|-Zhyr(oNn`)w-6==Dv~i(PZSJjrco=zAbmwGdc3J*JoVF9 zwbCDw1&mQ7tQo&IZHO_r^bTiE6k^oyM|z9&VvYC{Jiy&gBInv+&&O<(kj)?(0z1jN zsWc0r?DJMZ&NEslA7?@P;Lbuz`4hTYS7VC(NBmU9yg5(2@g_F| zCHa3~@Cmk;EF)m1vW06pGX}eN3DJ;s5iu(IIcTBy7GpoO!0cLimX9}F&6|8)F2ojvxT&yLi z@X`MhoOgW)bLY)QyZ2{sB|nY5R?%G zZ7tPME8Pe>4?d&BoYnMaY%^WhmVjxtpE(B87eKL`BYY7^<1$_^W{rKo^=U1P>pq!2 zTecJRT@isYUKhCexuR;cqc6isDq z7Nxt zZ|8#GJwaS05ebE_^`YBY7%s?^5-HOt=)R1^e}4}V(TxG)4Ay_OOih<%pd)Or22%0Q6T>VK3HjRomg}xwGV{h|eZ?}|a@Lo; ziqAy8Wo9J(T_t)qFt6|;J$$&&0t(oDCT}c{Y_HD(pHJnuY*rrRKI_6WLV~T3Beg3aO;KXVC{Lcnk4GzJlWARYS?mQRwT%kjHPAJp(3;jYU{Mrem9*^R4@Qm z+CQRg{%;|oAs?JJ3^K--FP$ECfN&S_AeCnT7e%}Apkod(PdSHjKbc3$=r{Ft^n&v2 z7Obw*fx`z(Aa%`rF#I6{UgCTTR-P>P_hC1bB{suof;mht`^NoJm))wB?=)>anusC<|Pt?CJ&7Gs6Y<%UVzqfF8H?8it&4RXq`8}I@YUL z&ifR&L><8uS>|v(-<4dL91V}oNXXZUf5Nb{dO-RoI7h#+&wkA;YBtFZiq^@Iy9rb1 z!q4pdx=@B={naF7j}p~~C1^F%50k6~d6PwSaYm6JIj5b7X*d<8)Gv>&+2T+4OF?aSL5hDKyxjhlt$HXW`3-|L-R_!hM*tmSZn&f@T33 zxS=hLOTOBG^M|F#f8ssdNcc*EyAQ!(iM23k{%iVX?E<3a)QO{`ayVuE0tnH_#|GmE z80WGaZ!Rw47*#c)_}XxM@QU3(WoqE&%a=6iN-9JMcf!Gv&CuZF1$RPCIoa%aS5-a* zi*=vi)!*$H>THUEZ2}4=#{uOPn!)DkSEi*s0{d0t=&WhY)t-ofseO`=5*z?u4&-5! zK{On6?f}1`hdB4I2MR}K!Jgq#FjReyV}+Sy!Lz?uT{{)8>ocCN-Zh$Zew^Cc-DTbq zL0+c*Bes9?a)TlGGSZawCMBcBez_XA$!*jgb7syl#MErEDc#U3x^%L8{Q z(;C-0K-Pm28hgr&HZB^*RYG6!&#diOb80sYTJ#Mi|BgaXau*JWeZc8IE8)x?#-|mr z1tp&Yn7>wrJcCbQu$)33%e4J>?h)AC?q-a!QcN1Mg45(1r|NYcoLHxb;<75xv-k(7 z>^Tl!=jP(JEBdJNrUzdhxdFzfm7l_xYn9*q-hV>4W0wQNuSY7R22Ay{O)?7svd|_-iDKq8_CpqzdJ5ZM|fJPx zMmOc4?1hV<8NZG;30Bcgg>3pM`8!vG`Fh2D$H8c$H3_#A!`G1sn5?M|YXmmq?JG8P zQsHB`TJ#W39Df73N2Ji;Z5)glur6w!tI!qgj_$4D(AHRwA1Z9%#)fO0l;%cUeb)=; z8$}R~cL8$c!a+wd5st9D=Wcrs)>qL2kIh-fjn7n2{;CFr#}4C~m|QxI*x`J&y>RZ# zZgig;g*rzB6h6G*=jF#oz|$0W`2NZgtGC!<=kk;2&UnIQsaNse-q-lwAErTkO``o} z2SAIx@3eV8V5Uww{98PLkFGY;>X0Y+ENukxTwFo7r3TD@4WdGd9ch`wx;KODAnE)o z8eeOU{g%t2e0DFWG9K@i?`kCFFJpxI9D^kD8ECVz7Q4H}!7rLJZ{2sWmCk~rY+wEA zz9yO}Mqy#&XOi?NmA=!drtgD>;JNBJmahxN0z=ksdF3hE{bQMw#mV3^-+?UJQHTbM z*!?5b6?+^v(yOmNa%}Qi$Xfk$cyjg=29(aFkCeDv`K7DyTj>?*eE1Vylj7%%K1~EG z`?FNS_Z;wlw}OGU;^<<22o1{)(kzyD;|a`%-f2FNeT#8-3*Uj#$~bgCkxHNWhJ)+R zc${~$0OVN5RpL}*C{h%H#!PniJNcRPeRhPC`G4WqnK|h3pCd`in+Xzg-_cp8hL~4= z8~v#5%H1(q$le)KKUF;uPw*1hh*e3=SV-nSOzzi2?0)i3Ot`kuTU(xK8DZ^6OPaXh`{ z0PY+3%DpX+PJMZnux3Lrru2M(ZGqxYJwFaC_q=8Ip{Mf@)=hs`$LBs5zUx9-`A?gu*INWUjg+e*gH-+*ey3Fz7G4JVyn zLrc;Jc!_>^Mb!m1#+iZo12>L(%^+6#alyOQ3{RQ}al2<+0~0SL0B$1A)l9;sTRX`& z?PHj^?H76f_dS1n>#6-2}a zEAg6sHoiBMMG=R`@K@vo>~uSgP0qPsF8>^^U#^19`kvq?w1P&@X6zQd^63BcW8ns? zt~6b(2gy?Vso$9*yy9PtbA;!_+$;MLQ)eO~zv6{m)Q%l?xHRo9(Yd`Bs|I|b-;kfe zpBz{w{sQ)_jf}a#vJFdXNAdglT>R zM}bx^vxWH|41x2voU?dkGRU)CCfYv4r^k>4uwJvkUm5uPQ9aC@5lFn>`~`(lO(=`& zMvl%q_~PJ0>e%i)>!B|wv2JYr^mRBdWf=35E@NhL6@0Hw2fj3WnB2M>%@&H`=+qvf zKG_CNF3AR;m8L{ve1vnZQ68f2Yy;at!ym3l_SLQyboIJ|ipnD1$UJl{)IkRx; zJHP0l4S5O(;marK46c1 zH~u&k3YQ9yocwJIy!D=NbMqnCT;I$d1P`LM3jE?tY@MLHF z=@JX57(@K`Fp`|h2|?9YgIK>L9tSG=n4T{J?=SK3d?d#(YxyMJ;ny$7nN%0>c2q<4 z-D@D|SU>PF4#m7nuWM=&g`nb;Rk zL&F1EI43IwI}{3F1nz58|y@Q!^FwpBIY?4CHX;?1iaF^tusc2bLRF89KFRc9>J ziH)Av@&~=%Tmw3|fnH-wM`clE41YZhYQ=}BVZa$Wbyg&e%Xr3e-~7ByTB7(<&l=pr5CkjI(|0dF&8&AStYh$4+>;AF0Kx*Bk z$sTQ6ZWgx~Pk&B@XRBUeSUuCgjY7#n!#Z3r^$)(@a8W)cHwx1YR}dRGfEt0nFd?lL zS4!W;$i(Oh-4P+Hv>jVaCH7_!|FF87;Z?(Yt?R`7s){tcjm zjJr9j3Pb&N!ku5$us6qs&788B6nYLg2@dGFg>_OR%VH6*TX;gQ;s3;p*SN zsB|m}?IWI$!UOFrXCw@D8$Cd#-5Mlv+=NrmrjYg7m<22w9^A(FG6b?KQ!aPbwRmJ=VqS4tdK_{`rUX z)t}>>53fQIHm|Bjw<3Pk#x2jTppnW^oN#A5)EP$!?dt-kIA6?a5&_R8<OQV9PFA!Yg1C`)_5n-x*>=E^nB@N?jaP;JVYHlo9WWkqY%*6h|^Z}LGpP-{v>~T zq{Ie0#dW~OAs3w8OX1J_5nB1?BE|^wE5x+irjx^tAoqSR7LVPcJHNN1uUZy7_xl1< ztg5gunP1`H0ezUa{VjA?kD_@%1%^Ls1>K7ZEPK%bt$%qaYUjwjb!)L_)@2YG=t1cu zL4^;DkN!u-1&TKXfqU&|tf}Y2rZo;YsZp0(toDl|xIGkK#!Zd7RZ<40-+5xkmSPf? zu883$Qt|J#aWJtoWBuVb>4Usx>UZw~p6TkrNPlNk-EEEMclN-Novu;%@h{B%cA4Ws zl2A*mA4BH9Lvxo9l%JJD^G_Jy@&`5Gax4%Hg}+d+D8Z?b9&XX?sZgl7{t>T@E91@aDwrqh3FqsLa9k20X+<&UZXW;40f4e7-IsS|j1$ptj_Q-t7q_c7&? z9XyL(LUQBM(4^x#{IeaTPdX#%GMB@!ah5M`fi@!dWGP

4)z43UFS=r5DolvFS?; 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ɗ@w@=1i{yj5 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

md842Yc4RPvKl;WX~vq0P2lpM6>U2e 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 z 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

HP_5`8ZfyqTN_{50(Ddkvp$ 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

-[![Documentation Status](https://img.shields.io/github/deployments/pulp-platform/Deeploy/github-pages?logo=readthedocs&logoColor=white&label=Docs +![PyPI](https://img.shields.io/pypi/v/deeploy-pulp)[![Documentation Status](https://img.shields.io/github/deployments/pulp-platform/Deeploy/github-pages?logo=readthedocs&logoColor=white&label=Docs )](https://pulp-platform.github.io/Deeploy/) [![CI](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/ci-deeploy.yml) [![Deeploy Docker](https://github.com/pulp-platform/Deeploy/actions/workflows/docker-build-deeploy.yml/badge.svg)](https://github.com/pulp-platform/Deeploy/actions/workflows/docker-build-deeploy.yml) @@ -35,7 +35,7 @@ git submodule update --init --recursive Installing Deeploy is as simple as running: ``` -pip install -e . --extra-index-url=https://pypi.ngc.nvidia.com +pip install -e . ``` However, to run the code generated by Deeploy on a certain target, you need the toolchains and the simulators associated with this platform. @@ -50,7 +50,7 @@ docker run -it --name deeploy_main -v $(pwd):/app/Deeploy ghcr.io/pulp-platform/ Install Deeploy inside the container in editable mode: ``` cd Deeploy -pip install -e . --extra-index-url=https://pypi.ngc.nvidia.com +pip install -e . ``` Congratulations, you installed Deeploy and its dependencies! Now, to test your installation let's run one simple test on each platform with the following commands: ``` diff --git a/cmake/simulation.cmake b/cmake/simulation.cmake index 756da8d282..8d68a0ad05 100644 --- a/cmake/simulation.cmake +++ b/cmake/simulation.cmake @@ -42,9 +42,13 @@ macro(print_simulation_config) endmacro() macro(add_banshee_simulation name) + if(NOT DEFINED ENV{BANSHEE_INSTALL_DIR}) + message(FATAL_ERROR "Environment variable BANSHEE_INSTALL_DIR not set") + endif() + set(BANSHEE_EXECUTABLE "$ENV{BANSHEE_INSTALL_DIR}/banshee") add_custom_target(banshee_${name} DEPENDS ${name} - COMMAND RUST_MIN_STACK=${banshee_stack_size} banshee + COMMAND RUST_MIN_STACK=${banshee_stack_size} ${BANSHEE_EXECUTABLE} --num-cores=${num_threads} --num-clusters=1 --latency diff --git a/docs/index.rst b/docs/index.rst index f765a041cd..dc32dbbce3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,3 +24,4 @@ Deeploy is developed as part of the PULP project, a joint effort between ETH Zur tutorials/overview structure apidocs + releasing diff --git a/docs/install.md b/docs/install.md index f2749867b4..ca85e1acea 100644 --- a/docs/install.md +++ b/docs/install.md @@ -47,14 +47,6 @@ pip install -e . ## Testing Framework Installation -Please make sure to use a Rust version that is compatible with LLVM 15, like 1.63.0: - -``` -sudo snap install rustup --classic -rustup install 1.63.0 -rustup default 1.63.0 -``` - The Makefile expects the environemt variable `CMAKE` to be defined. In case you have no strong preferences, you may run ``` @@ -84,7 +76,5 @@ For example, you can run ``` cd DeeployTest -python testRunner_generic.py -t Tests/Others/SimpleRegression +python testRunner_generic.py -t ./Tests/Kernels/Integer/Add/Regular ``` - -to run the `simpleRegression` test on your workstation. Various other tests are available and compatibility between tests and platforms is tested in the `.gitlab-ci.yml` file. diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000000..62dca8dc63 --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,18 @@ +# Deeploy Release Guide + +This guide explains how to prepare and publish a Deeploy release to PyPI/TestPyPI using `uv`. + +## Prepare the release +1. **Update the changelog** – Add a section for the new version under [CHANGELOG.md](../CHANGELOG.md) with the release date and noteworthy entries. +2. **Bump the version** – Use `uv` so the version in [pyproject.toml](../pyproject.toml) stays authoritative: + ```bash + uv version --bump major/minor/patch + ``` +3. **Verify the build locally** – This is optional but highly recommended: + ```bash + uv build + uv run --isolated --no-project --with dist/*.whl python -c "import Deeploy" + uv run --isolated --no-project --with dist/*.tar.gz python -c "import Deeploy" + ``` +4. **Commit and merge the changes** – Include the updated version and changelog in the commit. Once your commit reaches the `main` branch, it will be tagged. +5. **Deployment** – The publish workflow triggers on tags that start with `v` and match the version. Your package is now published congrats. diff --git a/pyproject.toml b/pyproject.toml index 0dda1a55b3..3a924a22b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 [project] -name = "PULP-Deeploy" -version = '0.2.1' +name = "deeploy-pulp" +version = "0.2.1" description = "Deeploy - DNN Compiler for Heterogeneous SoCs" authors = [ { name="Victor Jung", email="jungvi@iis.ee.ethz.ch" }, @@ -22,7 +22,7 @@ dependencies = [ 'numpy<2.0.0', 'onnx', 'onnxruntime', -'onnx-graphsurgeon==0.3.20', +'onnx-graphsurgeon>=0.5.8', 'mako', 'argparse', 'toml', diff --git a/toolchain/banshee.patch b/toolchain/banshee.patch deleted file mode 100644 index 51fdc946ce..0000000000 --- a/toolchain/banshee.patch +++ /dev/null @@ -1,103 +0,0 @@ -diff --git a/Cargo.toml b/Cargo.toml -index d406357..f14c0f7 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -11,30 +11,34 @@ edition = "2018" - build = "build/build.rs" - - [dependencies] --anyhow = "1" --binread = "2.2.0" --bytebuffer = "0.2.1" --byteorder = "1.4.3" --clap = "2" -+anyhow = "=1" -+binread = "=2.2.0" -+bytebuffer = "=0.2.1" -+byteorder = "=1.4.3" -+unicode-width = "=0.1.13" -+clap = "=2" - crossbeam-utils = "0.8" --csv = "1.0.0-beta.2" --elf = "0.0.10" -+csv = "=1.0.0-beta.2" -+elf = "=0.0.10" - flexfloat = { path = "flexfloat" } --itertools = "0.9" --llvm-sys = "120" --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" --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" -+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" -+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 -+++ b/build/runtime.rs -@@ -22,8 +22,7 @@ pub fn build() { - "--crate-type=staticlib", - "-Copt-level=3", - "-Cdebuginfo=0", -- "-Cpanic=abort", -- "-Cllvm-args=-opaque-pointers=0", -+ "-Cpanic=abort" - ]) - .status() - .unwrap(); -diff --git a/src/engine.rs b/src/engine.rs -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 ---- a/src/tran.rs -+++ b/src/tran.rs -@@ -18,9 +18,10 @@ use std::{ - collections::{BTreeSet, HashMap}, - ffi::CString, - }; -+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; From c547dd524a6bad39ac4ea936d11915da32c96a5a Mon Sep 17 00:00:00 2001 From: Victor Jung <33875047+Victor-Jung@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:48:23 +0100 Subject: [PATCH 28/28] Prepare for Release v0.2.1 (#158) Update CHANGELOG --- CHANGELOG.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f135d18cd7..cc185c7459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,25 @@ # Changelog This file contains the changelog for the Deeploy project. The changelog is divided into sections based on the version of the project. Each section contains a list of pull requests, features, changes, fixes, and removals that were made in that version. -## Unreleased (Planned Release Target: v0.2.1) +## Unreleased (Planned Release Target: v0.2.2) + + +### List of Pull Requests +- + +### Added +- + +### Changed +- + +### Fixed +- + +### Removed +- + +## Release v0.2.1 (2026-02-05) [#158](https://github.com/pulp-platform/Deeploy/pull/158) ### List of Pull Requests - PyPi Package Deployment + Remove Banshee Dept [#154](https://github.com/pulp-platform/Deeploy/pull/154)