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 e74c7e5ad2..6b104c7770 100644 Binary files a/DeeployTest/Tests/Adder/inputs.npz and b/DeeployTest/Tests/Adder/inputs.npz differ 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 9a8d6680e3..f73b28d551 100644 Binary files a/DeeployTest/Tests/Adder/outputs.npz and b/DeeployTest/Tests/Adder/outputs.npz differ diff --git a/DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz b/DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz new file mode 100644 index 0000000000..db396786bd Binary files /dev/null and b/DeeployTest/Tests/testTypeInferenceDifferentTypes/inputs.npz differ 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 0000000000..2269dd7292 Binary files /dev/null and b/DeeployTest/Tests/testTypeInferenceDifferentTypes/outputs.npz differ diff --git a/DeeployTest/generateNetwork.py b/DeeployTest/generateNetwork.py index a8a533db7b..bf590f06b1 100644 --- a/DeeployTest/generateNetwork.py +++ b/DeeployTest/generateNetwork.py @@ -26,6 +26,7 @@ # limitations under the License. import os +import sys import numpy as np import onnx @@ -35,8 +36,10 @@ from testUtils.graphDebug import generateDebugConfig from testUtils.platformMapping import mapDeployer, mapPlatform from testUtils.testRunner import TestGeneratorArgumentParser -from testUtils.typeMapping import inferInputType +from testUtils.typeMapping import inferInputType, parseDataType +from Deeploy.AbstractDataTypes import PointerClass +from Deeploy.CommonExtensions.DataTypes import IntegerDataTypes from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.DebugPasses import EmulateCMSISRequantPass from Deeploy.DeeployTypes import _NoVerbosity from Deeploy.Targets.CortexM.Platform import CMSISPlatform @@ -44,22 +47,8 @@ _TEXT_ALIGN = 30 -if __name__ == '__main__': - - parser = TestGeneratorArgumentParser(description = "Deeploy Code Generation Utility.") - parser.add_argument('--debug', - dest = 'debug', - action = 'store_true', - default = False, - help = 'Enable debugging mode\n') - parser.add_argument('--profileUntiled', - action = 'store_true', - dest = 'profileUntiled', - default = False, - help = 'Profile Untiled for L2\n') - - args = parser.parse_args() +def generateNetwork(args): onnx_graph = onnx.load_model(f'{args.dir}/network.onnx') graph = gs.import_onnx(onnx_graph) @@ -73,7 +62,38 @@ else: activations = None - tensors = graph.tensors() + # build {name, type} and {name, offset} maps + manual_types = {} + manual_offsets = {} + for kv in args.input_type_map: + try: + name, tstr = kv.split('=', 1) + except ValueError as exc: + raise ValueError(f"Invalid --input-type-map entry '{kv}'. Expected NAME=TYPE.") from exc + name, tstr = name.strip(), tstr.strip() + try: + manual_types[name] = parseDataType(tstr) + except ValueError as exc: + raise ValueError(f"Invalid --input-type-map entry '{kv}': {exc}") from exc + for kv in args.input_offset_map: + try: + name, ostr = kv.split('=', 1) + except ValueError as exc: + raise ValueError(f"Invalid --input-offset-map entry '{kv}'. Expected NAME=OFFSET.") from exc + name, ostr = name.strip(), ostr.strip() + try: + manual_offsets[name] = int(ostr) + except ValueError as exc: + raise ValueError(f"Invalid --input-offset-map entry '{kv}': OFFSET must be an integer.") from exc + + # Sanity check for unknown input names + manual_keys = set(manual_types) + assert manual_keys == set( + manual_offsets + ), f"Override inputs should have both type and offset specified. Inputs without both specified: {manual_keys ^ set(manual_types)}" + assert manual_keys <= set( + inputs.files + ), f"Unknown input names in overrides: {manual_keys - set(inputs.files)} (Valid names are: {set(inputs.files)})" if args.debug: test_inputs, test_outputs, graph = generateDebugConfig(inputs, outputs, activations, graph) @@ -90,11 +110,33 @@ platform, signProp = mapPlatform(args.platform) - for index, num in enumerate(test_inputs): - # WIESP: Do not infer types and offset of empty arrays + for index, (name, num) in enumerate(zip(inputs.files, test_inputs)): if np.prod(num.shape) == 0: continue - _type, offset = inferInputType(num, signProp)[0] + + if name in manual_keys: + _type = manual_types[name] + offset = manual_offsets[name] + + # Check if the provided values fit into the dereferenced type + vals = num.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} " + f"does not match input values in range [{vals.min()}, {vals.max()}] " + f"(expected range [{lo}, {hi}])") + + # 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}'.") + + _type = PointerClass(_type) + else: + _type, offset = inferInputType(num, signProp)[0] + inputTypes[f"input_{index}"] = _type inputOffsets[f"input_{index}"] = offset @@ -116,8 +158,8 @@ # Create input and output vectors os.makedirs(f'{args.dumpdir}', exist_ok = True) - - testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets) + 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() @@ -151,4 +193,49 @@ print("=" * 80) print() print(f"{'Number of Ops:' :<{_TEXT_ALIGN}} {num_ops}") - print(f"{'Model Parameters: ' :<{_TEXT_ALIGN}} {deployer.getParameterSize()}") \ No newline at end of file + print(f"{'Model Parameters: ' :<{_TEXT_ALIGN}} {deployer.getParameterSize()}") + + +if __name__ == '__main__': + + parser = TestGeneratorArgumentParser(description = "Deeploy Code Generation Utility.") + parser.add_argument('--debug', + dest = 'debug', + action = 'store_true', + default = False, + help = 'Enable debugging mode\n') + parser.add_argument('--profileUntiled', + action = 'store_true', + dest = 'profileUntiled', + default = False, + help = 'Profile Untiled for L2\n') + parser.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 ...') + parser.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 ...') + parser.add_argument('--shouldFail', action = 'store_true') + parser.set_defaults(shouldFail = False) + + args = parser.parse_args() + + try: + generateNetwork(args) + except Exception as e: + if args.shouldFail: + print("\033[92mNetwork generation ended, failed as expected!\033[0m") + sys.exit(0) + else: + raise e + + if args.shouldFail: + raise RuntimeError("Expected to fail!") diff --git a/DeeployTest/testMVP.py b/DeeployTest/testMVP.py index ff7a3ccf3a..6f0342e7b4 100644 --- a/DeeployTest/testMVP.py +++ b/DeeployTest/testMVP.py @@ -358,7 +358,8 @@ def setupDeployer(graph: gs.Graph, memoryHierarchy: MemoryHierarchy, defaultTarg # Create input and output vectors os.makedirs(f'{args.dumpdir}', exist_ok = True) - testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets) + print("=" * 80) + testInputStr = generateTestInputsHeader(deployer, test_inputs, inputTypes, inputOffsets, args.verbose) f = open(f'{args.dumpdir}/testinputs.h', "w") f.write(testInputStr) f.close() diff --git a/DeeployTest/testUtils/codeGenerate.py b/DeeployTest/testUtils/codeGenerate.py index 7df306efdb..5e572643a4 100644 --- a/DeeployTest/testUtils/codeGenerate.py +++ b/DeeployTest/testUtils/codeGenerate.py @@ -24,7 +24,6 @@ # limitations under the License. import os -from pprint import pprint from typing import Dict, List, Optional, Tuple import numpy as np @@ -51,7 +50,11 @@ def _shapeBroadcast(ctxt, value, name): return broadcastNum -def generateTestInputsHeader(deployer: NetworkDeployer, test_inputs: List, inputTypes: Dict, inputOffsets: Dict) -> 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