From ec044790fb97a46e1b2c325d12235f39580ec238 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 8 Jan 2025 23:37:41 -0500 Subject: [PATCH] Revert "Sync: `commaai/openpilot:master` into `sunnypilot/sunnypilot:master-new`" (#543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "Sync: `commaai/openpilot:master` into `sunnypilot/sunnypilot:master-n…" This reverts commit e6829571017bc2ee0b569235ef67df3d1ca1eace. --- .github/PULL_REQUEST_TEMPLATE/bugfix.md | 15 + .github/PULL_REQUEST_TEMPLATE/car_bugfix.md | 19 + .github/PULL_REQUEST_TEMPLATE/car_port.md | 15 + .github/PULL_REQUEST_TEMPLATE/fingerprint.md | 13 + .github/PULL_REQUEST_TEMPLATE/refactor.md | 15 + .github/PULL_REQUEST_TEMPLATE/tuning.md | 31 + .github/build.py | 30 + SConstruct | 4 + cereal/maptile.capnp | 49 ++ common/params.cc | 1 + common/util.cc | 23 - common/util.h | 1 - docs/CARS.md | 9 +- opendbc_repo | 2 +- panda | 2 +- pyproject.toml | 6 +- scripts/build_small.sh | 39 ++ scripts/code_stats.py | 54 ++ scripts/count_cars.py | 11 + scripts/git_rewrite/rewrite-git-history.sh | 391 ++++++++++++ scripts/git_rewrite/rewrite.sh | 59 ++ scripts/git_rewrite/tag-commit-map.txt | 82 +++ scripts/pyqt_demo.py | 14 + selfdrive/assets/offroad/icon_plus.png | 3 + selfdrive/debug/internal/__init__.py | 0 .../{ => internal}/fuzz_fw_fingerprint.py | 0 .../measure_modeld_packet_drop.py | 0 .../measure_torque_time_to_max.py | 0 selfdrive/debug/{ => internal}/qlog_size.py | 0 selfdrive/debug/touch_replay.py | 2 +- selfdrive/modeld/SConscript | 4 + selfdrive/modeld/constants.py | 20 +- selfdrive/modeld/fill_model_msg.py | 20 +- selfdrive/modeld/modeld.py | 28 +- selfdrive/modeld/models/commonmodel.cc | 6 +- selfdrive/modeld/models/supercombo.onnx | 4 +- selfdrive/modeld/parse_model_outputs.py | 2 - .../modeld/tests/snpe_benchmark/.gitignore | 1 + .../modeld/tests/snpe_benchmark/benchmark.cc | 192 ++++++ .../modeld/tests/snpe_benchmark/benchmark.sh | 4 + selfdrive/test/ciui.py | 58 ++ selfdrive/test/docker_tag_multiarch.sh | 25 + selfdrive/test/loop_until_fail.sh | 8 + .../process_replay/imgproc_replay_ref_hash | 1 + selfdrive/test/process_replay/model_replay.py | 2 +- selfdrive/test/process_replay/test_imgproc.py | 98 +++ selfdrive/test/profiling/.gitignore | 2 + selfdrive/test/profiling/__init__.py | 0 selfdrive/test/profiling/lib.py | 91 +++ selfdrive/test/profiling/profiler.py | 97 +++ system/athena/registration.py | 8 +- system/athena/tests/test_registration.py | 2 + system/hardware/tici/hardware.h | 12 +- system/manager/manager.py | 5 +- system/manager/process_config.py | 7 +- system/timed.py | 2 +- .../libPlatformValidatorShared.so | 3 + .../snpe/aarch64-ubuntu-gcc7.5/libSNPE.so | 3 + .../aarch64-ubuntu-gcc7.5/libcalculator.so | 3 + .../snpe/aarch64-ubuntu-gcc7.5/libhta.so | 3 + .../libsnpe_dsp_domains_v2.so | 3 + third_party/snpe/dsp/libcalculator_skel.so | 3 + .../dsp/libsnpe_dsp_v65_domains_v2_skel.so | 3 + .../dsp/libsnpe_dsp_v66_domains_v2_skel.so | 3 + .../dsp/libsnpe_dsp_v68_domains_v3_skel.so | 3 + third_party/snpe/include/DiagLog/IDiagLog.hpp | 84 +++ third_party/snpe/include/DiagLog/Options.hpp | 79 +++ .../snpe/include/DlContainer/IDlContainer.hpp | 191 ++++++ third_party/snpe/include/DlSystem/DlEnums.hpp | 234 ++++++++ third_party/snpe/include/DlSystem/DlError.hpp | 259 ++++++++ .../snpe/include/DlSystem/DlOptional.hpp | 225 +++++++ .../snpe/include/DlSystem/DlVersion.hpp | 78 +++ .../include/DlSystem/IBufferAttributes.hpp | 86 +++ .../include/DlSystem/IOBufferDataTypeMap.hpp | 127 ++++ third_party/snpe/include/DlSystem/ITensor.hpp | 146 +++++ .../snpe/include/DlSystem/ITensorFactory.hpp | 92 +++ .../snpe/include/DlSystem/ITensorItr.hpp | 182 ++++++ .../snpe/include/DlSystem/ITensorItrImpl.hpp | 42 ++ third_party/snpe/include/DlSystem/IUDL.hpp | 105 ++++ .../snpe/include/DlSystem/IUserBuffer.hpp | 358 +++++++++++ .../include/DlSystem/IUserBufferFactory.hpp | 81 +++ .../snpe/include/DlSystem/PlatformConfig.hpp | 230 +++++++ .../snpe/include/DlSystem/RuntimeList.hpp | 154 +++++ third_party/snpe/include/DlSystem/String.hpp | 104 ++++ .../snpe/include/DlSystem/StringList.hpp | 107 ++++ .../snpe/include/DlSystem/TensorMap.hpp | 120 ++++ .../snpe/include/DlSystem/TensorShape.hpp | 203 +++++++ .../snpe/include/DlSystem/TensorShapeMap.hpp | 127 ++++ .../snpe/include/DlSystem/UDLContext.hpp | 243 ++++++++ third_party/snpe/include/DlSystem/UDLFunc.hpp | 87 +++ .../snpe/include/DlSystem/UserBufferMap.hpp | 122 ++++ .../snpe/include/DlSystem/UserMemoryMap.hpp | 129 ++++ .../snpe/include/DlSystem/ZdlExportDefine.hpp | 13 + .../PlatformValidator/PlatformValidator.hpp | 118 ++++ .../include/SNPE/ApplicationBufferMap.hpp | 101 ++++ third_party/snpe/include/SNPE/PSNPE.hpp | 205 +++++++ .../snpe/include/SNPE/RuntimeConfigList.hpp | 85 +++ third_party/snpe/include/SNPE/SNPE.hpp | 258 ++++++++ third_party/snpe/include/SNPE/SNPEBuilder.hpp | 306 ++++++++++ third_party/snpe/include/SNPE/SNPEFactory.hpp | 220 +++++++ .../snpe/include/SNPE/UserBufferList.hpp | 49 ++ third_party/snpe/include/SnpeUdo/UdoBase.h | 537 +++++++++++++++++ third_party/snpe/include/SnpeUdo/UdoImpl.h | 343 +++++++++++ third_party/snpe/include/SnpeUdo/UdoImplCpu.h | 44 ++ third_party/snpe/include/SnpeUdo/UdoImplDsp.h | 207 +++++++ third_party/snpe/include/SnpeUdo/UdoImplGpu.h | 112 ++++ third_party/snpe/include/SnpeUdo/UdoReg.h | 108 ++++ third_party/snpe/include/SnpeUdo/UdoShared.h | 48 ++ third_party/snpe/larch64 | 1 + third_party/snpe/x86_64 | 1 + .../snpe/x86_64-linux-clang/libHtpPrepare.so | 3 + .../snpe/x86_64-linux-clang/libSNPE.so | 3 + third_party/snpe/x86_64-linux-clang/libomp.so | 3 + tinygrad_repo | 2 +- tools/cabana/binaryview.cc | 75 +-- tools/cabana/binaryview.h | 16 +- tools/cabana/chart/chart.cc | 2 - tools/cabana/chart/chartswidget.cc | 56 +- tools/cabana/chart/chartswidget.h | 3 - tools/cabana/chart/sparkline.cc | 8 +- tools/cabana/dbc/dbc.cc | 1 - tools/cabana/dbc/dbc.h | 4 +- tools/cabana/detailwidget.cc | 62 +- tools/cabana/detailwidget.h | 3 +- tools/cabana/mainwin.cc | 1 - tools/cabana/messageswidget.cc | 23 +- tools/cabana/settings.cc | 5 + tools/cabana/signalview.cc | 2 +- tools/cabana/streams/abstractstream.cc | 58 +- tools/cabana/streams/abstractstream.h | 10 +- tools/cabana/streams/replaystream.cc | 7 +- tools/cabana/streams/replaystream.h | 1 + tools/cabana/utils/util.h | 1 - tools/cabana/videowidget.cc | 193 +++--- tools/cabana/videowidget.h | 25 +- tools/install_python_dependencies.sh | 7 +- tools/latencylogger/README.md | 90 +++ tools/latencylogger/latency_logger.py | 239 ++++++++ tools/plotjuggler/README.md | 2 +- tools/plotjuggler/layouts/demo.xml | 104 ++++ tools/replay/replay.cc | 69 ++- tools/replay/replay.h | 11 +- tools/replay/seg_mgr.cc | 2 +- tools/replay/seg_mgr.h | 4 +- tools/replay/timeline.cc | 4 +- tools/replay/timeline.h | 22 +- tools/rerun/README.md | 6 +- tools/rerun/run.sh | 9 + tools/webcam/README.md | 28 +- tools/webcam/camerad.py | 15 +- tools/webcam/start_camerad.sh | 14 + uv.lock | 563 ++++++++++-------- 152 files changed, 9343 insertions(+), 780 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE/bugfix.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/car_bugfix.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/car_port.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/fingerprint.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/refactor.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/tuning.md create mode 100644 .github/build.py create mode 100644 cereal/maptile.capnp create mode 100755 scripts/build_small.sh create mode 100755 scripts/code_stats.py create mode 100755 scripts/count_cars.py create mode 100755 scripts/git_rewrite/rewrite-git-history.sh create mode 100755 scripts/git_rewrite/rewrite.sh create mode 100644 scripts/git_rewrite/tag-commit-map.txt create mode 100755 scripts/pyqt_demo.py create mode 100644 selfdrive/assets/offroad/icon_plus.png create mode 100644 selfdrive/debug/internal/__init__.py rename selfdrive/debug/{ => internal}/fuzz_fw_fingerprint.py (100%) rename selfdrive/debug/{ => internal}/measure_modeld_packet_drop.py (100%) rename selfdrive/debug/{ => internal}/measure_torque_time_to_max.py (100%) rename selfdrive/debug/{ => internal}/qlog_size.py (100%) create mode 100644 selfdrive/modeld/tests/snpe_benchmark/.gitignore create mode 100644 selfdrive/modeld/tests/snpe_benchmark/benchmark.cc create mode 100755 selfdrive/modeld/tests/snpe_benchmark/benchmark.sh create mode 100755 selfdrive/test/ciui.py create mode 100755 selfdrive/test/docker_tag_multiarch.sh create mode 100755 selfdrive/test/loop_until_fail.sh create mode 100644 selfdrive/test/process_replay/imgproc_replay_ref_hash create mode 100644 selfdrive/test/process_replay/test_imgproc.py create mode 100644 selfdrive/test/profiling/.gitignore create mode 100644 selfdrive/test/profiling/__init__.py create mode 100644 selfdrive/test/profiling/lib.py create mode 100755 selfdrive/test/profiling/profiler.py create mode 100644 third_party/snpe/aarch64-ubuntu-gcc7.5/libPlatformValidatorShared.so create mode 100644 third_party/snpe/aarch64-ubuntu-gcc7.5/libSNPE.so create mode 100644 third_party/snpe/aarch64-ubuntu-gcc7.5/libcalculator.so create mode 100644 third_party/snpe/aarch64-ubuntu-gcc7.5/libhta.so create mode 100644 third_party/snpe/aarch64-ubuntu-gcc7.5/libsnpe_dsp_domains_v2.so create mode 100644 third_party/snpe/dsp/libcalculator_skel.so create mode 100644 third_party/snpe/dsp/libsnpe_dsp_v65_domains_v2_skel.so create mode 100644 third_party/snpe/dsp/libsnpe_dsp_v66_domains_v2_skel.so create mode 100644 third_party/snpe/dsp/libsnpe_dsp_v68_domains_v3_skel.so create mode 100644 third_party/snpe/include/DiagLog/IDiagLog.hpp create mode 100644 third_party/snpe/include/DiagLog/Options.hpp create mode 100644 third_party/snpe/include/DlContainer/IDlContainer.hpp create mode 100644 third_party/snpe/include/DlSystem/DlEnums.hpp create mode 100644 third_party/snpe/include/DlSystem/DlError.hpp create mode 100644 third_party/snpe/include/DlSystem/DlOptional.hpp create mode 100644 third_party/snpe/include/DlSystem/DlVersion.hpp create mode 100644 third_party/snpe/include/DlSystem/IBufferAttributes.hpp create mode 100644 third_party/snpe/include/DlSystem/IOBufferDataTypeMap.hpp create mode 100644 third_party/snpe/include/DlSystem/ITensor.hpp create mode 100644 third_party/snpe/include/DlSystem/ITensorFactory.hpp create mode 100644 third_party/snpe/include/DlSystem/ITensorItr.hpp create mode 100644 third_party/snpe/include/DlSystem/ITensorItrImpl.hpp create mode 100644 third_party/snpe/include/DlSystem/IUDL.hpp create mode 100644 third_party/snpe/include/DlSystem/IUserBuffer.hpp create mode 100644 third_party/snpe/include/DlSystem/IUserBufferFactory.hpp create mode 100644 third_party/snpe/include/DlSystem/PlatformConfig.hpp create mode 100644 third_party/snpe/include/DlSystem/RuntimeList.hpp create mode 100644 third_party/snpe/include/DlSystem/String.hpp create mode 100644 third_party/snpe/include/DlSystem/StringList.hpp create mode 100644 third_party/snpe/include/DlSystem/TensorMap.hpp create mode 100644 third_party/snpe/include/DlSystem/TensorShape.hpp create mode 100644 third_party/snpe/include/DlSystem/TensorShapeMap.hpp create mode 100644 third_party/snpe/include/DlSystem/UDLContext.hpp create mode 100644 third_party/snpe/include/DlSystem/UDLFunc.hpp create mode 100644 third_party/snpe/include/DlSystem/UserBufferMap.hpp create mode 100644 third_party/snpe/include/DlSystem/UserMemoryMap.hpp create mode 100644 third_party/snpe/include/DlSystem/ZdlExportDefine.hpp create mode 100644 third_party/snpe/include/PlatformValidator/PlatformValidator.hpp create mode 100644 third_party/snpe/include/SNPE/ApplicationBufferMap.hpp create mode 100644 third_party/snpe/include/SNPE/PSNPE.hpp create mode 100644 third_party/snpe/include/SNPE/RuntimeConfigList.hpp create mode 100644 third_party/snpe/include/SNPE/SNPE.hpp create mode 100644 third_party/snpe/include/SNPE/SNPEBuilder.hpp create mode 100644 third_party/snpe/include/SNPE/SNPEFactory.hpp create mode 100644 third_party/snpe/include/SNPE/UserBufferList.hpp create mode 100644 third_party/snpe/include/SnpeUdo/UdoBase.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoImpl.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoImplCpu.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoImplDsp.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoImplGpu.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoReg.h create mode 100644 third_party/snpe/include/SnpeUdo/UdoShared.h create mode 120000 third_party/snpe/larch64 create mode 120000 third_party/snpe/x86_64 create mode 100644 third_party/snpe/x86_64-linux-clang/libHtpPrepare.so create mode 100644 third_party/snpe/x86_64-linux-clang/libSNPE.so create mode 100755 third_party/snpe/x86_64-linux-clang/libomp.so create mode 100644 tools/latencylogger/README.md create mode 100755 tools/latencylogger/latency_logger.py create mode 100644 tools/plotjuggler/layouts/demo.xml create mode 100755 tools/rerun/run.sh create mode 100755 tools/webcam/start_camerad.sh diff --git a/.github/PULL_REQUEST_TEMPLATE/bugfix.md b/.github/PULL_REQUEST_TEMPLATE/bugfix.md new file mode 100644 index 0000000000..e28661db3b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bugfix.md @@ -0,0 +1,15 @@ +--- +name: Bug fix +about: For openpilot bug fixes +title: '' +labels: 'bugfix' +assignees: '' +--- + +**Description** + + + +**Verification** + + diff --git a/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md new file mode 100644 index 0000000000..76c86346c8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md @@ -0,0 +1,19 @@ +--- +name: Car Bug fix +about: For vehicle/brand specific bug fixes +title: '' +labels: 'car bug fix' +assignees: '' +--- + +**Description** + + + +**Verification** + + + +**Route** + +Route: [a route with the bug fix] diff --git a/.github/PULL_REQUEST_TEMPLATE/car_port.md b/.github/PULL_REQUEST_TEMPLATE/car_port.md new file mode 100644 index 0000000000..c7aa2b96c2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/car_port.md @@ -0,0 +1,15 @@ +--- +name: Car port +about: For new car ports +title: '' +labels: 'car port' +assignees: '' +--- + +**Checklist** + +- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs +- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py) +- [ ] route with openpilot: +- [ ] route with stock system: +- [ ] car harness used (if comma doesn't sell it, put N/A): diff --git a/.github/PULL_REQUEST_TEMPLATE/fingerprint.md b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md new file mode 100644 index 0000000000..b94f7dc53f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/fingerprint.md @@ -0,0 +1,13 @@ +--- +name: Fingerprint +about: For adding fingerprints to existing cars +title: '' +labels: 'fingerprint' +assignees: '' +--- + +**Car** +Which car (make, model, year) this fingerprint is for + +**Route** +A route with the fingerprint \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/refactor.md b/.github/PULL_REQUEST_TEMPLATE/refactor.md new file mode 100644 index 0000000000..1ee21c1bba --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/refactor.md @@ -0,0 +1,15 @@ +--- +name: Refactor +about: For code refactors +title: '' +labels: 'refactor' +assignees: '' +--- + +**Description** + + + +**Verification** + + diff --git a/.github/PULL_REQUEST_TEMPLATE/tuning.md b/.github/PULL_REQUEST_TEMPLATE/tuning.md new file mode 100644 index 0000000000..4397e5ad20 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/tuning.md @@ -0,0 +1,31 @@ +--- +name: Tuning +about: For openpilot tuning changes +title: '' +labels: 'tuning' +assignees: '' +--- + +**Description** + + + +**Verification** + + \ No newline at end of file diff --git a/.github/build.py b/.github/build.py new file mode 100644 index 0000000000..e141ea05df --- /dev/null +++ b/.github/build.py @@ -0,0 +1,30 @@ +import pathlib + +GITHUB_FOLDER = pathlib.Path(__file__).parent + +PULL_REQUEST_TEMPLATES = (GITHUB_FOLDER / "PULL_REQUEST_TEMPLATE") + +order = ["fingerprint", "car_bugfix", "bugfix", "car_port", "refactor"] + +def create_pull_request_template(): + with open(GITHUB_FOLDER / "pull_request_template.md", "w") as f: + f.write("\n\n") + + for t in order: + template = PULL_REQUEST_TEMPLATES / f"{t}.md" + text = template.read_text() + + # Remove metadata for GitHub + start = text.find("---") + end = text.find("---", start+1) + text = text[end + 4:] + + # Remove comments + text = text.replace("", "") + + f.write(f"\n\n") + +create_pull_request_template() diff --git a/SConstruct b/SConstruct index ee52fd1203..39f7d14d03 100644 --- a/SConstruct +++ b/SConstruct @@ -49,6 +49,10 @@ AddOption('--ccflags', default='', help='pass arbitrary flags over the command line') +AddOption('--snpe', + action='store_true', + help='use SNPE on PC') + AddOption('--external-sconscript', action='store', metavar='FILE', diff --git a/cereal/maptile.capnp b/cereal/maptile.capnp new file mode 100644 index 0000000000..c8a23a1822 --- /dev/null +++ b/cereal/maptile.capnp @@ -0,0 +1,49 @@ +using Cxx = import "./include/c++.capnp"; +$Cxx.namespace("cereal"); + +@0xa086df597ef5d7a0; + +# Geometry +struct Point { + x @0: Float64; + y @1: Float64; + z @2: Float64; +} + +struct PolyLine { + points @0: List(Point); +} + +# Map features +struct Lane { + id @0 :Text; + + leftBoundary @1 :LaneBoundary; + rightBoundary @2 :LaneBoundary; + + leftAdjacentId @3 :Text; + rightAdjacentId @4 :Text; + + inboundIds @5 :List(Text); + outboundIds @6 :List(Text); + + struct LaneBoundary { + polyLine @0 :PolyLine; + startHeading @1 :Float32; # WRT north + } +} + +# Map tiles +struct TileSummary { + version @0 :Text; + updatedAt @1 :UInt64; # Millis since epoch + + level @2 :UInt8; + x @3 :UInt16; + y @4 :UInt16; +} + +struct MapTile { + summary @0 :TileSummary; + lanes @1 :List(Lane); +} diff --git a/common/params.cc b/common/params.cc index cd4c406030..a1e881c39b 100644 --- a/common/params.cc +++ b/common/params.cc @@ -133,6 +133,7 @@ std::unordered_map keys = { {"GsmRoaming", PERSISTENT | BACKUP}, {"HardwareSerial", PERSISTENT}, {"HasAcceptedTerms", PERSISTENT}, + {"IMEI", PERSISTENT}, {"InstallDate", PERSISTENT}, {"IsDriverViewEnabled", CLEAR_ON_MANAGER_START}, {"IsEngaged", PERSISTENT}, diff --git a/common/util.cc b/common/util.cc index f4c69eb269..5ffd6e4099 100644 --- a/common/util.cc +++ b/common/util.cc @@ -255,29 +255,6 @@ bool ends_with(const std::string& s, const std::string& suffix) { strcmp(s.c_str() + (s.size() - suffix.size()), suffix.c_str()) == 0; } -std::string strip(const std::string &str) { - auto should_trim = [](unsigned char ch) { - // trim whitespace or a null character - return std::isspace(ch) || ch == '\0'; - }; - - size_t start = 0; - while (start < str.size() && should_trim(static_cast(str[start]))) { - start++; - } - - if (start == str.size()) { - return ""; - } - - size_t end = str.size() - 1; - while (end > 0 && should_trim(static_cast(str[end]))) { - end--; - } - - return str.substr(start, end - start + 1); -} - std::string check_output(const std::string& command) { char buffer[128]; std::string result; diff --git a/common/util.h b/common/util.h index d4106b5002..7cfa008509 100644 --- a/common/util.h +++ b/common/util.h @@ -74,7 +74,6 @@ float getenv(const char* key, float default_val); std::string hexdump(const uint8_t* in, const size_t size); bool starts_with(const std::string &s1, const std::string &s2); bool ends_with(const std::string &s, const std::string &suffix); -std::string strip(const std::string &str); // ***** random helpers ***** int random_int(int min, int max); diff --git a/docs/CARS.md b/docs/CARS.md index 10d10d4cfc..c0b0f1706e 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. -# 290 Supported Cars +# 289 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Hardware Needed
 |Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -56,7 +56,6 @@ A supported vehicle is one that just works when you install a comma device. All |Genesis|GV60 (Performance Trim) 2022-23[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Genesis|GV70 (2.5T Trim, without HDA II) 2022-23[5](#footnotes)|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai L connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Genesis|GV70 (3.5T Trim, without HDA II) 2022-23[5](#footnotes)|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai M connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Genesis|GV70 Electrified (Australia Only) 2022[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Genesis|GV70 Electrified (with HDA II) 2023[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Genesis|GV80 2023[5](#footnotes)|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai M connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[1](#footnotes)|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 GM connector
- 1 comma 3X
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| @@ -80,7 +79,7 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Passport 2019-23|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Ridgeline 2017-25|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Ridgeline 2017-24|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Azera 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Azera Hybrid 2019|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai C connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Azera Hybrid 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| @@ -92,7 +91,7 @@ A supported vehicle is one that just works when you install a comma device. All |Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Hyundai J connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Hyundai|Ioniq 5 (Non-US only) 2022-24[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (with HDA II) 2022-24[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (without HDA II) 2022-24[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 6 (with HDA II) 2023-24[5](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| @@ -295,7 +294,7 @@ A supported vehicle is one that just works when you install a comma device. All |Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Volkswagen|Tiguan 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,12](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 USB-C coupler
- 1 VW J533 connector
- 1 comma 3X
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/opendbc_repo b/opendbc_repo index 6ddebc9a03..6525e8b600 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 6ddebc9a0365d3421bee7cceddb0263c88fb78dd +Subproject commit 6525e8b6006f37a1d809d2a617a876410c484ca1 diff --git a/panda b/panda index 781af8b4f1..0d4b79a3c7 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 781af8b4f1144cf8d1f17e75017589e2013e3cf9 +Subproject commit 0d4b79a3c7b9c1012832ec414989e56e3a2a8d46 diff --git a/pyproject.toml b/pyproject.toml index 47a6a37cfe..7a889584a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,6 +103,7 @@ dev = [ "lru-dict", "matplotlib", "parameterized >=0.8, <0.9", + #"pprofile", "pyautogui", "pyopencl; platform_machine != 'aarch64'", # broken on arm64 "pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version @@ -111,10 +112,13 @@ dev = [ "tabulate", "types-requests", "types-tabulate", + + # this is only pinned since 5.15.11 is broken + "pyqt5 ==5.15.2; platform_machine == 'x86_64'", # no aarch64 wheels for macOS/linux ] tools = [ - "metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')", + "metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal/metadrive_simulator-0.4.2.3-py3-none-any.whl ; (platform_machine != 'aarch64')", "rerun-sdk >= 0.18", ] diff --git a/scripts/build_small.sh b/scripts/build_small.sh new file mode 100755 index 0000000000..176ca5aaa8 --- /dev/null +++ b/scripts/build_small.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -ex + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +# git clone --mirror +SRC=/tmp/openpilot.git/ +OUT=/tmp/smallpilot/ + +echo "starting size $(du -hs .git/)" + +rm -rf $OUT + +cd $SRC +git remote update + +# copy contents +#rsync -a --exclude='.git/' $DIR $OUT + +cp -r $SRC $OUT + +cd $OUT + +# remove all tags +git tag -l | xargs git tag -d + +# remove non-master branches +BRANCHES="release2 release3 devel master-ci nightly" +for branch in $BRANCHES; do + git branch -D $branch + git branch -D ${branch}-staging || true +done + +#git gc +git reflog expire --expire=now --all +git gc --prune=now +git gc --aggressive --prune=now +echo "new one is $(du -hs .)" diff --git a/scripts/code_stats.py b/scripts/code_stats.py new file mode 100755 index 0000000000..1ffc8901bd --- /dev/null +++ b/scripts/code_stats.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import os +import ast +import stat +import subprocess + +fouts = {x.decode('utf-8') for x in subprocess.check_output(['git', 'ls-files']).strip().split()} + +pyf = [] +for d in ["cereal", "common", "scripts", "selfdrive", "tools"]: + for root, _, files in os.walk(d): + for f in files: + if f.endswith(".py"): + pyf.append(os.path.join(root, f)) + +imps: set[str] = set() + +class Analyzer(ast.NodeVisitor): + def visit_Import(self, node): + for alias in node.names: + imps.add(alias.name) + self.generic_visit(node) + + def visit_ImportFrom(self, node): + imps.add(node.module) + self.generic_visit(node) + +tlns = 0 +carlns = 0 +scriptlns = 0 +testlns = 0 +for f in sorted(pyf): + if f not in fouts: + continue + xbit = bool(os.stat(f)[stat.ST_MODE] & stat.S_IXUSR) + src = open(f).read() + lns = len(src.split("\n")) + tree = ast.parse(src) + Analyzer().visit(tree) + print(f"{lns:5d} {f} {xbit}") + if 'test' in f: + testlns += lns + elif f.startswith(('tools/', 'scripts/', 'selfdrive/debug')): + scriptlns += lns + elif f.startswith('selfdrive/car'): + carlns += lns + else: + tlns += lns + +print(f"{tlns} lines of openpilot python") +print(f"{carlns} lines of car ports") +print(f"{scriptlns} lines of tools/scripts/debug") +print(f"{testlns} lines of tests") +#print(sorted(list(imps))) diff --git a/scripts/count_cars.py b/scripts/count_cars.py new file mode 100755 index 0000000000..19f486735a --- /dev/null +++ b/scripts/count_cars.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +from collections import Counter +from pprint import pprint + +from opendbc.car.docs import get_all_car_docs + +if __name__ == "__main__": + cars = get_all_car_docs() + make_count = Counter(l.make for l in cars) + print("\n", "*" * 20, len(cars), "total", "*" * 20, "\n") + pprint(make_count) diff --git a/scripts/git_rewrite/rewrite-git-history.sh b/scripts/git_rewrite/rewrite-git-history.sh new file mode 100755 index 0000000000..cce4455ce5 --- /dev/null +++ b/scripts/git_rewrite/rewrite-git-history.sh @@ -0,0 +1,391 @@ +#!/usr/bin/env bash +set -e + +SRC=/tmp/openpilot/ +SRC_CLONE=/tmp/openpilot-clone/ +OUT=/tmp/openpilot-tiny/ + +REWRITE_IGNORE_BRANCHES=( + dashcam3 + devel + master-ci + nightly + release2 + release3 + release3-staging +) + +VALIDATE_IGNORE_FILES=( + ".github/ISSUE_TEMPLATE/bug_report.md" + ".github/pull_request_template.md" +) + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +LOGS_DIR=$DIR/git-rewrite-$(date +"%Y-%m-%dT%H:%M:%S%z") +mkdir -p $LOGS_DIR + +GIT_REWRITE_LOG=$LOGS_DIR/git-rewrite-log.txt +BRANCH_DIFF_LOG=$LOGS_DIR/branch-diff-log.txt +COMMIT_DIFF_LOG=$LOGS_DIR/commit-diff-log.txt + +START_TIME=$(date +%s) +exec > >(while IFS= read -r line; do + CURRENT_TIME=$(date +%s) + ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) + echo "[${ELAPSED_TIME}s] $line" +done | tee -a "$GIT_REWRITE_LOG") 2>&1 + +# INSTALL git-filter-repo +if [ ! -f /tmp/git-filter-repo ]; then + echo "Installing git-filter-repo..." + curl -sSo /tmp/git-filter-repo https://raw.githubusercontent.com/newren/git-filter-repo/main/git-filter-repo + chmod +x /tmp/git-filter-repo +fi + +# MIRROR openpilot +if [ ! -d $SRC ]; then + echo "Mirroring openpilot..." + git clone --mirror https://github.com/commaai/openpilot.git $SRC # 4.18 GiB (488034 objects) + + cd $SRC + + echo "Starting size $(du -sh .)" + + git remote update + + # the git-filter-repo analysis is bliss - can be found in the repo root/filter-repo/analysis + echo "Analyzing with git-filter-repo..." + /tmp/git-filter-repo --force --analyze + + echo "Pushing to openpilot-archive..." + # push to archive repo - in smaller parts because the 2 GB push limit - https://docs.github.com/en/get-started/using-git/troubleshooting-the-2-gb-push-limit + ARCHIVE_REPO=git@github.com:commaai/openpilot-archive.git + git push --prune $ARCHIVE_REPO +refs/heads/master:refs/heads/master # push master first so it's the default branch (when openpilot-archive is an empty repo) + git push --prune $ARCHIVE_REPO +refs/heads/*:refs/heads/* # 956.39 MiB (110725 objects) + git push --prune $ARCHIVE_REPO +refs/tags/*:refs/tags/* # 1.75 GiB (21694 objects) + # git push --mirror $ARCHIVE_REPO || true # fails to push refs/pull/* (deny updating a hidden ref) for pull requests + # we fail and continue - more reading: https://stackoverflow.com/a/34266401/639708 and https://blog.plataformatec.com.br/2013/05/how-to-properly-mirror-a-git-repository/ +fi + +# REWRITE master and tags +if [ ! -d $SRC_CLONE ]; then + echo "Cloning $SRC..." + GIT_LFS_SKIP_SMUDGE=1 git clone $SRC $SRC_CLONE + + cd $SRC_CLONE + + echo "Checking out old history..." + + git checkout tags/v0.7.1 > /dev/null 2>&1 + # checkout as main, since we need master ref later + git checkout -b main + + echo "Creating setup commits..." + + # rm these so we don't get conflicts later + git rm -r cereal opendbc panda selfdrive/ui/ui > /dev/null + git commit -m "removed conflicting files" > /dev/null + + # skip-smudge to get rid of some lfs errors that it can't find the reference of some lfs files + # we don't care about fetching/pushing lfs right now + git lfs install --skip-smudge --local + + # squash initial setup commits + git cherry-pick -n -X theirs 6c33a5c..59b3d06 > /dev/null + git commit -m "switching to master" > /dev/null + + # squash the two commits + git reset --soft HEAD~2 + git commit -m "switching to master" -m "$(git log --reverse --format=%B 6c33a5c..59b3d06)" -m "removed conflicting files" > /dev/null + + # get commits we want to cherry-pick + # will start with the next commit after #59b3d06 tools is local now + COMMITS=$(git rev-list --reverse 59b3d06..master) + + # we need this for logging + TOTAL_COMMITS=$(echo $COMMITS | wc -w | xargs) + CURRENT_COMMIT_NUMBER=0 + + # empty this file + > commit-map.txt + + echo "Rewriting master commits..." + + for COMMIT in $COMMITS; do + CURRENT_COMMIT_NUMBER=$((CURRENT_COMMIT_NUMBER + 1)) + # echo -ne "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Cherry-picking commit: $COMMIT"\\r + echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Cherry-picking commit: $COMMIT" + + # set environment variables to preserve author/committer and dates + export GIT_AUTHOR_NAME=$(git show -s --format='%an' $COMMIT) + export GIT_AUTHOR_EMAIL=$(git show -s --format='%ae' $COMMIT) + export GIT_COMMITTER_NAME=$(git show -s --format='%cn' $COMMIT) + export GIT_COMMITTER_EMAIL=$(git show -s --format='%ce' $COMMIT) + export GIT_AUTHOR_DATE=$(git show -s --format='%ad' $COMMIT) + export GIT_COMMITTER_DATE=$(git show -s --format='%cd' $COMMIT) + + # cherry-pick the commit + if ! GIT_OUTPUT=$(git cherry-pick -m 1 -X theirs $COMMIT 2>&1); then + # check if the failure is because of an empty commit + if [[ "$GIT_OUTPUT" == *"The previous cherry-pick is now empty"* ]]; then + echo "Empty commit detected. Skipping commit $COMMIT" + git cherry-pick --skip + # log it was empty to the mapping file + echo "$COMMIT EMPTY" >> commit-map.txt + else + # handle other errors or conflicts + echo "Cherry-pick failed. Handling error..." + echo "$GIT_OUTPUT" + exit 1 + fi + else + # capture the new commit hash + NEW_COMMIT=$(git rev-parse HEAD) + + # save the old and new commit hashes to the mapping file + echo "$COMMIT $NEW_COMMIT" >> commit-map.txt + + # append the old commit ID to the commit message + git commit --amend -m "$(git log -1 --pretty=%B)" -m "Former-commit-id: $COMMIT" > /dev/null + fi + + # prune every 3000 commits to avoid gc errors + if [ $((CURRENT_COMMIT_NUMBER % 3000)) -eq 0 ]; then + echo "Pruning repo..." + git gc + fi + done + + echo "Rewriting tags..." + + # remove all old tags + git tag -l | xargs git tag -d + + # read each line from the tag-commit-map.txt + while IFS=' ' read -r TAG OLD_COMMIT; do + # search for the new commit in commit-map.txt corresponding to the old commit + NEW_COMMIT=$(grep "^$OLD_COMMIT " "commit-map.txt" | awk '{print $2}') + + # check if this is a rebased commit + if [ -z "$NEW_COMMIT" ]; then + # if not, then just use old commit hash + NEW_COMMIT=$OLD_COMMIT + fi + + echo "Rewriting tag $TAG from commit $NEW_COMMIT" + git tag -f "$TAG" "$NEW_COMMIT" + done < "$DIR/tag-commit-map.txt" + + # uninstall lfs since we don't want to touch (push to) lfs right now + # git push will also push lfs, if we don't uninstall (--local so just for this repo) + git lfs uninstall --local + + # force push new master + git push --force origin main:master + + # force push new tags + git push --force --tags +fi + +# REWRITE branches based on master +if [ ! -f "$SRC_CLONE/rewrite-branches-done" ]; then + cd $SRC_CLONE + > rewrite-branches-done + + # empty file + > $BRANCH_DIFF_LOG + + echo "Rewriting branches based on master..." + + # will store raw diffs here, if exist + mkdir -p differences + + # get a list of all branches except master and REWRITE_IGNORE_BRANCHES + BRANCHES=$(git branch -r | grep -v ' -> ' | sed 's/.*origin\///' | grep -v '^master$' | grep -v -f <(echo "${REWRITE_IGNORE_BRANCHES[*]}" | tr ' ' '\n')) + + for BRANCH in $BRANCHES; do + # check if the branch is based on master history + MERGE_BASE=$(git merge-base master origin/$BRANCH) || true + if [ -n "$MERGE_BASE" ]; then + echo "Rewriting branch: $BRANCH" + + # create a new branch based on the new master + NEW_MERGE_BASE=$(grep "^$MERGE_BASE " "commit-map.txt" | awk '{print $2}') + if [ -z "$NEW_MERGE_BASE" ]; then + echo "Error: could not find new merge base for branch $BRANCH" >> $BRANCH_DIFF_LOG + continue + fi + git checkout -b ${BRANCH}_new $NEW_MERGE_BASE + + # get the range of commits unique to this branch + COMMITS=$(git rev-list --reverse $MERGE_BASE..origin/${BRANCH}) + + HAS_ERROR=0 + + # simple delimiter + echo "BRANCH ${BRANCH}" >> commit-map.txt + + for COMMIT in $COMMITS; do + # set environment variables to preserve author/committer and dates + export GIT_AUTHOR_NAME=$(git show -s --format='%an' $COMMIT) + export GIT_AUTHOR_EMAIL=$(git show -s --format='%ae' $COMMIT) + export GIT_COMMITTER_NAME=$(git show -s --format='%cn' $COMMIT) + export GIT_COMMITTER_EMAIL=$(git show -s --format='%ce' $COMMIT) + export GIT_AUTHOR_DATE=$(git show -s --format='%ad' $COMMIT) + export GIT_COMMITTER_DATE=$(git show -s --format='%cd' $COMMIT) + + # cherry-pick the commit + if ! GIT_OUTPUT=$(git cherry-pick -m 1 -X theirs $COMMIT 2>&1); then + # check if the failure is because of an empty commit + if [[ "$GIT_OUTPUT" == *"The previous cherry-pick is now empty"* ]]; then + echo "Empty commit detected. Skipping commit $COMMIT" + git cherry-pick --skip + # log it was empty to the mapping file + echo "$COMMIT EMPTY" >> commit-map.txt + else + # handle other errors or conflicts + echo "Cherry-pick of ${BRANCH} branch failed. Removing branch upstream..." >> $BRANCH_DIFF_LOG + echo "$GIT_OUTPUT" > "$LOGS_DIR/branch-${BRANCH}" + git cherry-pick --abort + git push --delete origin ${BRANCH} + HAS_ERROR=1 + break + fi + else + # capture the new commit hash + NEW_COMMIT=$(git rev-parse HEAD) + + # save the old and new commit hashes to the mapping file + echo "$COMMIT $NEW_COMMIT" >> commit-map.txt + + # append the old commit ID to the commit message + git commit --amend -m "$(git log -1 --pretty=%B)" -m "Former-commit-id: $COMMIT" > /dev/null + fi + done + + # force push the new branch + if [ $HAS_ERROR -eq 0 ]; then + # git lfs goes haywire here, so we need to install and uninstall + # git lfs install --skip-smudge --local + git lfs uninstall --local > /dev/null + git push -f origin ${BRANCH}_new:${BRANCH} + fi + + # clean up local branch + git checkout master > /dev/null + git branch -D ${BRANCH}_new > /dev/null + else + echo "Deleting branch $BRANCH as it's not based on master history" >> $BRANCH_DIFF_LOG + git push --delete origin ${BRANCH} + fi + done +fi + +# VALIDATE cherry-pick +if [ ! -f "$SRC_CLONE/validation-done" ]; then + cd $SRC_CLONE + > validation-done + + TOTAL_COMMITS=$(grep -cve '^\s*$' commit-map.txt) + CURRENT_COMMIT_NUMBER=0 + COUNT_SAME=0 + COUNT_DIFF=0 + + # empty file + > $COMMIT_DIFF_LOG + + echo "Validating commits..." + + # will store raw diffs here, if exist + mkdir -p differences + + # read each line from commit-map.txt + while IFS=' ' read -r OLD_COMMIT NEW_COMMIT; do + if [ "$NEW_COMMIT" == "EMPTY" ]; then + continue + fi + if [ "$OLD_COMMIT" == "BRANCH" ]; then + echo "Branch ${NEW_COMMIT} below:" >> $COMMIT_DIFF_LOG + continue + fi + CURRENT_COMMIT_NUMBER=$((CURRENT_COMMIT_NUMBER + 1)) + # retrieve short hashes and dates for the old and new commits + OLD_COMMIT_SHORT=$(git rev-parse --short $OLD_COMMIT) + NEW_COMMIT_SHORT=$(git rev-parse --short $NEW_COMMIT) + OLD_DATE=$(git show -s --format='%cd' $OLD_COMMIT) + NEW_DATE=$(git show -s --format='%cd' $NEW_COMMIT) + + # echo -ne "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Comparing old commit $OLD_COMMIT_SHORT ($OLD_DATE) with new commit $NEW_COMMIT_SHORT ($NEW_DATE)"\\r + echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Comparing old commit $OLD_COMMIT_SHORT ($OLD_DATE) with new commit $NEW_COMMIT_SHORT ($NEW_DATE)" + + # generate lists of files and their hashes for the old and new commits, excluding ignored files + OLD_FILES=$(git ls-tree -r $OLD_COMMIT | grep -vE "$(IFS='|'; echo "${VALIDATE_IGNORE_FILES[*]}")") + NEW_FILES=$(git ls-tree -r $NEW_COMMIT | grep -vE "$(IFS='|'; echo "${VALIDATE_IGNORE_FILES[*]}")") + + # Compare the diffs + if diff <(echo "$OLD_FILES") <(echo "$NEW_FILES") > /dev/null; then + # echo "Old commit $OLD_COMMIT_SHORT and new commit $NEW_COMMIT_SHORT are equivalent." + COUNT_SAME=$((COUNT_SAME + 1)) + else + echo "[$CURRENT_COMMIT_NUMBER/$TOTAL_COMMITS] Difference found between old commit $OLD_COMMIT_SHORT and new commit $NEW_COMMIT_SHORT" >> $COMMIT_DIFF_LOG + COUNT_DIFF=$((COUNT_DIFF + 1)) + set +e + diff -u <(echo "$OLD_FILES") <(echo "$NEW_FILES") > "$LOGS_DIR/commit-$CURRENT_COMMIT_NUMBER-$OLD_COMMIT_SHORT-$NEW_COMMIT_SHORT" + set -e + fi + done < "commit-map.txt" + + echo "Summary:" >> $COMMIT_DIFF_LOG + echo "Equivalent commits: $COUNT_SAME" >> $COMMIT_DIFF_LOG + echo "Different commits: $COUNT_DIFF" >> $COMMIT_DIFF_LOG +fi + +if [ ! -d $OUT ]; then + cp -r $SRC $OUT + + cd $OUT + + # remove all non-master branches + # git branch | grep -v "^ master$" | grep -v "\*" | xargs git branch -D + + # echo "cleaning up refs" + # delete pull request refs since we can't alter them anyway (https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally#error-failed-to-push-some-refs) + # git for-each-ref --format='%(refname)' | grep '^refs/pull/' | xargs -I {} git update-ref -d {} + + echo "importing new lfs files" + # import "almost" everything to lfs + BRANCHES=$(git for-each-ref --format='%(refname)' refs/heads/ | sed 's%refs/heads/%%g' | grep -v -f <(echo "${REWRITE_IGNORE_BRANCHES[*]}" | tr ' ' '\n') | tr '\n' ' ') + git lfs migrate import --include="*.dlc,*.onnx,*.svg,*.png,*.gif,*.ttf,*.wav,selfdrive/car/tests/test_models_segs.txt,system/hardware/tici/updater,selfdrive/ui/qt/spinner_larch64,selfdrive/ui/qt/text_larch64,third_party/**/*.a,third_party/**/*.so,third_party/**/*.so.*,third_party/**/*.dylib,third_party/acados/*/t_renderer,third_party/qt5/larch64/bin/lrelease,third_party/qt5/larch64/bin/lupdate,third_party/catch2/include/catch2/catch.hpp,*.apk,*.apkpatch,*.jar,*.pdf,*.jpg,*.mp3,*.thneed,*.tar.gz,*.npy,*.csv,*.a,*.so*,*.dylib,*.o,*.b64,selfdrive/hardware/tici/updater,selfdrive/boardd/tests/test_boardd,selfdrive/ui/qt/spinner_aarch64,installer/updater/updater,selfdrive/debug/profiling/simpleperf/**/*,selfdrive/hardware/eon/updater,selfdrive/ui/qt/text_aarch64,selfdrive/debug/profiling/pyflame/**/*,installer/installers/installer_openpilot,installer/installers/installer_dashcam,selfdrive/ui/text/text,selfdrive/ui/android/text/text,selfdrive/ui/spinner/spinner,selfdrive/visiond/visiond,selfdrive/loggerd/loggerd,selfdrive/sensord/sensord,selfdrive/sensord/gpsd,selfdrive/ui/android/spinner/spinner,selfdrive/ui/qt/spinner,selfdrive/ui/qt/text,_stringdefs.py,dfu-util-aarch64-linux,dfu-util-aarch64,dfu-util-x86_64-linux,dfu-util-x86_64,stb_image.h,clpeak3,clwaste,apk/**/*,external/**/*,phonelibs/**/*,third_party/boringssl/**/*,flask/**/*,panda/**/*,board/**/*,messaging/**/*,opendbc/**/*,tools/cabana/chartswidget.cc,third_party/nanovg/**/*,selfdrive/controls/lib/lateral_mpc/lib_mpc_export/**/*,selfdrive/ui/paint.cc,werkzeug/**/*,pyextra/**/*,third_party/android_hardware_libhardware/**/*,selfdrive/controls/lib/lead_mpc_lib/lib_mpc_export/**/*,selfdrive/locationd/laikad.py,selfdrive/locationd/test/test_laikad.py,tools/gpstest/test_laikad.py,selfdrive/locationd/laikad_helpers.py,tools/nui/**/*,jsonrpc/**/*,selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/**/*,selfdrive/controls/lib/lateral_mpc/mpc_export/**/*,selfdrive/camerad/cameras/camera_qcom.cc,selfdrive/manager.py,selfdrive/modeld/models/driving.cc,third_party/curl/**/*,selfdrive/modeld/thneed/debug/**/*,selfdrive/modeld/thneed/include/**/*,third_party/openmax/**/*,selfdrive/controls/lib/longitudinal_mpc/mpc_export/**/*,selfdrive/controls/lib/longitudinal_mpc_model/lib_mpc_export/**/*,Pipfile,Pipfile.lock,gunicorn/**/*,*.qm,jinja2/**/*,click/**/*,dbcs/**/*,websocket/**/*" $BRANCHES + + echo "reflog and gc" + # this is needed after lfs import + git reflog expire --expire=now --all + git gc --prune=now --aggressive + + # check the git-filter-repo analysis again - can be found in the repo root/filter-repo/analysis + echo "Analyzing with git-filter-repo..." + /tmp/git-filter-repo --force --analyze + + echo "New size is $(du -sh .)" +fi + +cd $OUT + +# fetch all lfs files from https://github.com/commaai/openpilot.git +# some lfs files are missing on gitlab, but they can be found on github +git config lfs.url https://github.com/commaai/openpilot.git/info/lfs +git config lfs.pushurl ssh://git@github.com/commaai/openpilot.git +git lfs fetch --all || true + +# also fetch all lfs files from https://gitlab.com/commaai/openpilot-lfs.git +git config lfs.url https://gitlab.com/commaai/openpilot-lfs.git/info/lfs +git config lfs.pushurl ssh://git@gitlab.com/commaai/openpilot-lfs.git +git lfs fetch --all || true + +# final push - will also push lfs +# TODO: switch to git@github.com:commaai/openpilot.git when ready +# git push --mirror git@github.com:commaai/openpilot-tiny.git +# using this instead to ignore refs/pull/* - since this is also what --mirror does - https://blog.plataformatec.com.br/2013/05/how-to-properly-mirror-a-git-repository/ +git push --prune git@github.com:commaai/openpilot-tiny.git +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/* diff --git a/scripts/git_rewrite/rewrite.sh b/scripts/git_rewrite/rewrite.sh new file mode 100755 index 0000000000..8a18b15bec --- /dev/null +++ b/scripts/git_rewrite/rewrite.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +git clone --bare https://github.com/commaai/openpilot +cp -r openpilot.git openpilot_backup +cd openpilot.git + +# backup old repo +git push git@github.com:commaai/openpilot-archive.git +refs/heads/master:refs/heads/master +git push git@github.com:commaai/openpilot-archive.git +refs/heads/*:refs/heads/* +git push git@github.com:commaai/openpilot-archive.git +refs/tags/*:refs/tags/* +git push --mirror git@github.com:commaai/openpilot-archive.git + +# ignore all release branches +git for-each-ref --format='delete %(refname)' | grep 'dashcam3\|devel\|master-ci\|nightly\|release2\|release3\|release3-staging' | git update-ref --stdin + +# re-tag old releases on master +declare -A TAGS=( ["f8cb04e4a8b032b72a909f68b808a50936184bee"]="v0.9.7" ["0b4d08fab8e35a264bc7383e878538f8083c33e5"]="v0.9.6" ["3b1e9017c560499786d8a0e46aaaeea65037acac"]="v0.9.5" ["fa310d9e2542cf497d92f007baec8fd751ffa99c"]="v0.9.4" ["8704c1ff952b5c85a44f50143bbd1a4f7b4887e2"]="v0.9.3" ["c7d3b28b93faa6c955fb24bc64031512ee985ee9"]="v0.9.2" ["89f68bf0cbf53a81b0553d3816fdbe522f941fa1"]="v0.9.1" ["58b84fb401a804967aa0dd5ee66fafa90194fd30"]="v0.9.0" ["f41dc62a12cc0f3cb8c5453c0caa0ba21e1bd01e"]="v0.8.16" ["5a7c2f90361e72e9c35e88abd2e11acdc4aba354"]="v0.8.15" ["71901c94dbbaa2f9f156a80c14cc7ea65219fc7c"]="v0.8.14" ["95da47079510afc91665263619e5939126da637c"]="v0.8.13" ["472177e2a8a1d002e56f9096326fd2dff62e54f9"]="v0.8.12" ["08078acbd0b4f7da469c7dff6159000e358974a9"]="v0.8.11" ["687925c775c375495f9827946138a724bde00b9d"]="v0.8.10" ["204e5a090735a059d69c29145a4cee49450da07e"]="v0.8.9" ["4be956f8861ecbb521ef9503a3c87b07c9d36721"]="v0.8.8" ["589f82c76627d634761a31a34b2488403556eb0b"]="v0.8.7" ["507cfc8910f74ddb8810039d68b880b426ff9ff9"]="v0.8.6" ["d47b00b45a866bef088f51d1ff31de5885ab04e9"]="v0.8.5" ["553e7d1cce314e7eb0587186b1764c3ff43bed62"]="v0.8.4" ["9896438d1511602a1ff87f7c4eb3c7172b30104a"]="v0.8.3" ["280192ed1443f112463417c2d815ea8ee2762fbd"]="v0.8.2" ["8039361567e4659eae2a084e6f39f34acadf4cac"]="v0.8.1" ["d56e04c0d960c8d3d4ab88b578dc508a2b4e07dc"]="v0.8" ["3d456e5d0fbf0c9887d0499dee812f2b029edf6d"]="v0.7.10" ["81763a18b5d0e379b749e090ecce36a91fca7c43"]="v0.7.9" ["9bc0b350fd273bbb2deb3dcaef0312944e4f6cfd"]="v0.7.8" ["ede5b632b58c55e4ff003f948efae07fe03c2280"]="v0.7.7" ["775acd11ba2e0a8c2f5a5655338718d796491b36"]="v0.7.6.1" ["302417b4cf0dcf00d45e4995b5410e543ad121d1"]="v0.7.5" ["12ff088b42221dd17d9d97decb1fc61a7cb0a861"]="v0.7.4" ["9563f7730252451fdcba9bc3d9fe36dab9c86a26"]="v0.7.3" ["8321cf283abbc2ca3fda7e0c7a069a77a492fe0c"]="v0.7.2" ["1e1de64a1e59476b7b3d3558b92149246d5c3292"]="v0.7.1" ["a2ae18d1dbd1e59c38ce22fa25ddffbd1d3084e3"]="v0.7" ["d4eb5a6eafdd4803d09e6f3963918216cca5a81f"]="v0.6.6" ["70d17cd69b80e7627dcad8fd5b6438f2309ac307"]="v0.6.5" ["58f376002e0c654fbc2de127765fa297cf694a33"]="v0.6.4" ["d5f9caa82d80cdcc7f1b7748f2cf3ccbf94f82a3"]="v0.6.3" ["095ef5f9f60fca1b269aabcc3cfd322b17b9e674"]="v0.6.2" ["cf5c4aeacb1703d0ffd35bdb5297d3494fee9a22"]="v0.6.1" ["60a20537c5f3fcc7f11946d81aebc8f90c08c117"]="v0.6" ["dd34ccfe288ebda8e2568cf550994ae890379f45"]="v0.5.13" ["3f9059fea886f1fa3b0c19a62a981d891dcc84eb"]="v0.5.12" ["2f92d577f995ff6ae1945ef6b89df3cb69b92999"]="v0.5.11" ["5a9d89ed42ddcd209d001a10d7eb828ef0e6d9de"]="v0.5.10" ["0207a970400ee28d3e366f2e8f5c551281accf02"]="v0.5.9" ["b967da5fc1f7a07e3561db072dd714d325e857b0"]="v0.5.8" ["210db686bb89f8696aa040e6e16de65424b808c9"]="v0.5.7" ["860a48765d1016ba226fb2c64aea35a45fe40e4a"]="v0.5.6" ["8f3539a27b28851153454eb737da9624cccaed2d"]="v0.5.5" ["a422246dc30bce11e970514f13f7c110f4470cc3"]="v0.5.4" ["285c52eb693265a0a530543e9ca0aeb593a2a55e"]="v0.5.3" ["0129a8a4ff8da5314e8e4d4d3336e89667ff6d54"]="v0.5.2" ["6f3d10a4c475c4c4509f0b370805419acd13912d"]="v0.5.1" ["de33bc46452b1046387ee2b3a03191b2c71135fb"]="v0.5" ["ae5cb7a0dab8b1bed9d52292f9b4e8e66a0f8ec9"]="v0.4.7" ["c6df34f55ba8c5a911b60d3f9eb20e3fa45f68c1"]="v0.4.6" ["37285038d3f91fa1b49159c4a35a8383168e644f"]="v0.4.5" ["9a9ff839a9b70cb2601d7696af743f5652395389"]="v0.4.4" ["28c0797d30175043bbfa31307b63aab4197cf996"]="v0.4.2" ["4474b9b3718653aeb0aee26422caefb90460cc0e"]="v0.4.1" ["da52d065a4c4f52d6017a537f3a80326f5af8bdc"]="v0.4.0.2" ["9d3963559ae7b15193057937ff3e72481899f40d"]="v0.3.5" ["1b8c44b5067525a5d266b6e99799d8097da76a29"]="v0.3.4" ["5cf91d0496688fed4f2a6c7021349b1fc0e057a2"]="v0.3.3" ["7fe46f1e1df5dec08a940451ba0feefd5c039165"]="v0.3.2" ["41e3a0f699f5c39cb61a15c0eb7a4aa816d47c24"]="v0.3.1" ["c5d8aec28b5230d34ae4b677c2091cc3dec7e3e8"]="v0.3.0" ["693bcb0f83478f2651db6bac9be5ca5ad60d03f3"]="v0.2.9" ["95a349abcc050712c50d4d85a1c8a804eee7f6c2"]="v0.2.8" ["c6ba5dc5391d3ca6cda479bf1923b88ce45509a0"]="v0.2.7" ["6c3afeec0fb439070b2912978b8dbb659033b1d9"]="v0.2.6" ["29c58b45882ac79595356caf98580c1d2a626011"]="v0.2.5" ["ecc565aa3fdc4c7e719aadc000e1fdc4d80d4fe0"]="v0.2.4" ["adaa4ed350acda4067fc0b455ad15b54cdf4c768"]="v0.2.3" ["a64b9aa9b8cb5863c917b6926516291a63c02fe5"]="v0.2.2" ["17d9becd3c673091b22f09aa02559a9ed9230f50"]="v0.2.1" ["449b482cc3236ccf31829830b4f6a44b2dcc06c2"]="v0.2" ["e94a30bec07e719c5a7b037ca1f4db8312702cce"]="v0.1" ) +for tag in "${!TAGS[@]}"; do git tag -f "${TAGS[$tag]}" "$tag" ; done + +# get master root commit +ROOT_COMMIT=$(git rev-list --max-parents=0 HEAD | tail -n 1) + +# link master and devel +git replace --graft $ROOT_COMMIT v0.7.1 +git-filter-repo --prune-empty never --force --commit-callback 'h=commit.original_id.decode("utf-8");m=commit.message.decode("utf-8");commit.message=str.encode(m + "\n" + "old-commit-hash: " + h)' + +# delete replace refs +git for-each-ref --format='delete %(refname)' refs/replace | git update-ref --stdin + +# machine validation +tail -n +2 "filter-repo/commit-map" | tr ' ' '\n' | xargs -P $(nproc) -n 2 bash -c 'H1=$(cd ../openpilot_backup && git ls-tree -r $0 | sha1sum) && H2=$(git ls-tree -r $1 | sha1sum) && echo "$H1 $H2" >> /tmp/GIT_HASHES && diff <(echo $H1) <(echo $H2) || exit 255' +# human validation +less /tmp/GIT_HASH + +# cleanup +git reflog expire --expire=now --all +git gc --prune=now --aggressive + +# get all lfs files +set +e +git config lfs.url https://github.com/commaai/openpilot.git/info/lfs +git lfs fetch --all +git config lfs.url https://gitlab.com/commaai/openpilot-lfs.git/info/lfs +git lfs fetch --all +set -e + +# add new files to lfs +git lfs migrate import --everything --include="*.ico,*.dlc,*.onnx,*.svg,*.png,*.gif,*.ttf,*.wav,system/hardware/tici/updater,selfdrive/ui/qt/spinner_larch64,selfdrive/ui/qt/text_larch64,third_party/**/*.a,third_party/**/*.so,third_party/**/*.so.*,third_party/**/*.dylib,third_party/acados/*/t_renderer,third_party/qt5/larch64/bin/lrelease,third_party/qt5/larch64/bin/lupdate,third_party/catch2/include/catch2/catch.hpp,*.apk,*.apkpatch,*.jar,*.pdf,*.jpg,*.mp3,*.thneed,*.tar.gz,*.npy,*.csv,*.a,*.so*,*.dylib,*.o,*.b64,selfdrive/hardware/tici/updater,selfdrive/boardd/tests/test_boardd,selfdrive/ui/qt/spinner_aarch64,installer/updater/updater,selfdrive/debug/profiling/simpleperf/**/*,selfdrive/hardware/eon/updater,selfdrive/ui/qt/text_aarch64,selfdrive/debug/profiling/pyflame/**/*,installer/installers/installer_openpilot,installer/installers/installer_dashcam,selfdrive/ui/text/text,selfdrive/ui/android/text/text,selfdrive/ui/spinner/spinner,selfdrive/visiond/visiond,selfdrive/loggerd/loggerd,selfdrive/sensord/sensord,selfdrive/sensord/gpsd,selfdrive/ui/android/spinner/spinner,selfdrive/ui/qt/spinner,selfdrive/ui/qt/text,_stringdefs.py,dfu-util-aarch64-linux,dfu-util-aarch64,dfu-util-x86_64-linux,dfu-util-x86_64,stb_image.h,clpeak3,clwaste,apk/**/*,external/**/*,phonelibs/**/*,third_party/boringssl/**/*,pyextra/**/*,panda/board/**/inc/*.h,panda/board/obj/*.elf,board/inc/*.h,third_party/nanovg/**/*,selfdrive/controls/lib/lateral_mpc/lib_mpc_export/**/*,pyextra/**/*,third_party/android_hardware_libhardware/**/*,selfdrive/controls/lib/lead_mpc_lib/lib_mpc_export/**/*,*.pro,selfdrive/controls/lib/longitudinal_mpc/lib_mpc_export/**/*,selfdrive/controls/lib/lateral_mpc/mpc_export/**/*,third_party/curl/**/*,selfdrive/modeld/thneed/debug/**/*,selfdrive/modeld/thneed/include/**/*,third_party/openmax/**/*,selfdrive/controls/lib/longitudinal_mpc/mpc_export/**/*,selfdrive/controls/lib/longitudinal_mpc_model/lib_mpc_export/**/*,Pipfile,Pipfile.lock,poetry.lock,*.qm" + +# set new lfs endpoint +git config lfs.url https://gitlab.com/commaai/openpilot-lfs.git/info/lfs +git config lfs.pushurl ssh://git@gitlab.com/commaai/openpilot-lfs.git + +# push all branch+tag (scary stuff...) +git push -f --set-upstream git@github.com:commaai/openpilot.git +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/* diff --git a/scripts/git_rewrite/tag-commit-map.txt b/scripts/git_rewrite/tag-commit-map.txt new file mode 100644 index 0000000000..66b1fb00c1 --- /dev/null +++ b/scripts/git_rewrite/tag-commit-map.txt @@ -0,0 +1,82 @@ +v0.1 e94a30bec07e719c5a7b037ca1f4db8312702cce +v0.2 449b482cc3236ccf31829830b4f6a44b2dcc06c2 +v0.2.1 17d9becd3c673091b22f09aa02559a9ed9230f50 +v0.2.2 a64b9aa9b8cb5863c917b6926516291a63c02fe5 +v0.2.3 adaa4ed350acda4067fc0b455ad15b54cdf4c768 +v0.2.4 ecc565aa3fdc4c7e719aadc000e1fdc4d80d4fe0 +v0.2.5 29c58b45882ac79595356caf98580c1d2a626011 +v0.2.6 6c3afeec0fb439070b2912978b8dbb659033b1d9 +v0.2.7 c6ba5dc5391d3ca6cda479bf1923b88ce45509a0 +v0.2.8 95a349abcc050712c50d4d85a1c8a804eee7f6c2 +v0.2.9 693bcb0f83478f2651db6bac9be5ca5ad60d03f3 +v0.3.0 c5d8aec28b5230d34ae4b677c2091cc3dec7e3e8 +v0.3.1 41e3a0f699f5c39cb61a15c0eb7a4aa816d47c24 +v0.3.2 7fe46f1e1df5dec08a940451ba0feefd5c039165 +v0.3.3 5cf91d0496688fed4f2a6c7021349b1fc0e057a2 +v0.3.4 1b8c44b5067525a5d266b6e99799d8097da76a29 +v0.3.5 b111277f464cf66fa34b67819a83ea683e0f64df +v0.4.0.2 da52d065a4c4f52d6017a537f3a80326f5af8bdc +v0.4.1 4474b9b3718653aeb0aee26422caefb90460cc0e +v0.4.2 28c0797d30175043bbfa31307b63aab4197cf996 +v0.4.4 9a9ff839a9b70cb2601d7696af743f5652395389 +v0.4.5 37285038d3f91fa1b49159c4a35a8383168e644f +v0.4.6 c6df34f55ba8c5a911b60d3f9eb20e3fa45f68c1 +v0.4.7 ae5cb7a0dab8b1bed9d52292f9b4e8e66a0f8ec9 +v0.5 de33bc46452b1046387ee2b3a03191b2c71135fb +v0.5.1 8f22f52235c48eada586795ac57edb22688e4d08 +v0.5.2 0129a8a4ff8da5314e8e4d4d3336e89667ff6d54 +v0.5.3 285c52eb693265a0a530543e9ca0aeb593a2a55e +v0.5.4 a422246dc30bce11e970514f13f7c110f4470cc3 +v0.5.5 8f3539a27b28851153454eb737da9624cccaed2d +v0.5.6 860a48765d1016ba226fb2c64aea35a45fe40e4a +v0.5.7 9ce3045f139ee29bf0eea5ec59dfe7df9c3d2c51 +v0.5.8 2cee2e05ba0f3824fdbb8b957958800fa99071a1 +v0.5.9 ad145da3bcded0fe75306df02061d07a633963c3 +v0.5.10 ff4c1557d8358f158f4358788ff18ef93d2470ef +v0.5.11 d1866845df423c6855e2b365ff230cf7d89a420b +v0.5.12 f6e8ef27546e9a406724841e75f8df71cc4c2c97 +v0.5.13 dd34ccfe288ebda8e2568cf550994ae890379f45 +v0.6 60a20537c5f3fcc7f11946d81aebc8f90c08c117 +v0.6.1 cf5c4aeacb1703d0ffd35bdb5297d3494fee9a22 +v0.6.2 095ef5f9f60fca1b269aabcc3cfd322b17b9e674 +v0.6.3 d5f9caa82d80cdcc7f1b7748f2cf3ccbf94f82a3 +v0.6.4 58f376002e0c654fbc2de127765fa297cf694a33 +v0.6.5 70d17cd69b80e7627dcad8fd5b6438f2309ac307 +v0.6.6 d4eb5a6eafdd4803d09e6f3963918216cca5a81f +v0.7 a2ae18d1dbd1e59c38ce22fa25ddffbd1d3084e3 +v0.7.1 1e1de64a1e59476b7b3d3558b92149246d5c3292 +v0.7.2 59bd58c940673b4c4a6a86f299022614bcf42b22 +v0.7.3 d7acd8b68f8131e0e714400cf124a3e228638643 +v0.7.4 e93649882c5e914eec4a8b8b593dc0587e497033 +v0.7.5 8abc0afe464626a461d2c7e192c912eeebeccc65 +v0.7.6 69aacd9d179fe6dd3110253a099c38b34cff7899 +v0.7.7 f1caed7299cdba5e45635d8377da6cc1e5fd7072 +v0.7.8 2189fe8741b635d8394d55dee28959425cfd5ad0 +v0.7.9 86dc54b836a973f132ed26db9f5a60b29f9b25b2 +v0.7.10 47a42ff432db8a2494e922ca5e767e58020f0446 +v0.7.11 f46ed718ba8d6bb4d42cd7b0f0150c406017c373 +v0.8 d56e04c0d960c8d3d4ab88b578dc508a2b4e07dc +v0.8.1 cd6f26664cb8d32a13847d6648567c47c580e248 +v0.8.2 7cc0999aebfe63b6bb6dd83c1dff62c3915c4820 +v0.8.3 986500fe2f10870018f1fba1e5465476b8915977 +v0.8.4 f0d0b82b8d6f5f450952113e234d0a5a49e80c48 +v0.8.5 f5d9ddc6c2a2802a61e5ce590c6b6688bf736a69 +v0.8.6 75904ed7452c6cbfb2a70cd379a899d8a75b97c2 +v0.8.7 4f9e568019492126e236da85b5ca0a059f292900 +v0.8.8 a949a49d5efaaf2d881143d23e9fb5ff9e28e88c +v0.8.9 a034926264cd1025c69d6ceb3fe444965f960b75 +v0.8.10 59accdd814398b884167c0f41dbf46dcccf0c29c +v0.8.11 d630ec9092f039cb5e51c5dd6d92fc47b91407e4 +v0.8.12 57871c99031cf597ffa0d819057ac1401e129f32 +v0.8.13 e43e6e876513450d235124fcb711f1724ed9814c +v0.8.14 71901c94dbbaa2f9f156a80c14cc7ea65219fc7c +v0.8.15 5a7c2f90361e72e9c35e88abd2e11acdc4aba354 +v0.8.16 f41dc62a12cc0f3cb8c5453c0caa0ba21e1bd01e +v0.9.0 58b84fb401a804967aa0dd5ee66fafa90194fd30 +v0.9.1 89f68bf0cbf53a81b0553d3816fdbe522f941fa1 +v0.9.2 c7d3b28b93faa6c955fb24bc64031512ee985ee9 +v0.9.3 8704c1ff952b5c85a44f50143bbd1a4f7b4887e2 +v0.9.4 fa310d9e2542cf497d92f007baec8fd751ffa99c +v0.9.5 3b1e9017c560499786d8a0e46aaaeea65037acac +v0.9.6 0b4d08fab8e35a264bc7383e878538f8083c33e5 +v0.9.7 f8cb04e4a8b032b72a909f68b808a50936184bee diff --git a/scripts/pyqt_demo.py b/scripts/pyqt_demo.py new file mode 100755 index 0000000000..783728bdb8 --- /dev/null +++ b/scripts/pyqt_demo.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +from PyQt5.QtWidgets import QApplication, QLabel +from openpilot.selfdrive.ui.qt.python_helpers import set_main_window + + +if __name__ == "__main__": + app = QApplication([]) + label = QLabel('Hello World!') + + # Set full screen and rotate + set_main_window(label) + + app.exec_() diff --git a/selfdrive/assets/offroad/icon_plus.png b/selfdrive/assets/offroad/icon_plus.png new file mode 100644 index 0000000000..6418a37a65 --- /dev/null +++ b/selfdrive/assets/offroad/icon_plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa3f1c39a4e82adfb52d43fc0ad6773a70dbaa4fc79109a7d6b6c1f73b298eac +size 2833 diff --git a/selfdrive/debug/internal/__init__.py b/selfdrive/debug/internal/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/debug/fuzz_fw_fingerprint.py b/selfdrive/debug/internal/fuzz_fw_fingerprint.py similarity index 100% rename from selfdrive/debug/fuzz_fw_fingerprint.py rename to selfdrive/debug/internal/fuzz_fw_fingerprint.py diff --git a/selfdrive/debug/measure_modeld_packet_drop.py b/selfdrive/debug/internal/measure_modeld_packet_drop.py similarity index 100% rename from selfdrive/debug/measure_modeld_packet_drop.py rename to selfdrive/debug/internal/measure_modeld_packet_drop.py diff --git a/selfdrive/debug/measure_torque_time_to_max.py b/selfdrive/debug/internal/measure_torque_time_to_max.py similarity index 100% rename from selfdrive/debug/measure_torque_time_to_max.py rename to selfdrive/debug/internal/measure_torque_time_to_max.py diff --git a/selfdrive/debug/qlog_size.py b/selfdrive/debug/internal/qlog_size.py similarity index 100% rename from selfdrive/debug/qlog_size.py rename to selfdrive/debug/internal/qlog_size.py diff --git a/selfdrive/debug/touch_replay.py b/selfdrive/debug/touch_replay.py index 6e5ecbbe5b..1e1596d264 100755 --- a/selfdrive/debug/touch_replay.py +++ b/selfdrive/debug/touch_replay.py @@ -30,7 +30,7 @@ if __name__ == '__main__': elif event.type == 3 and event.code == 57 and event.value == -1: fingers[current_slot] = [-1, -1] elif event.type == 3 and event.code == 53: - fingers[current_slot][1] = event.value + fingers[current_slot][1] = h - (h - event.value) if fingers[current_slot][0] != -1: touch_points.append(fingers[current_slot].copy()) elif event.type == 3 and event.code == 54: diff --git a/selfdrive/modeld/SConscript b/selfdrive/modeld/SConscript index cb0ce22d8b..ef0fd52f33 100644 --- a/selfdrive/modeld/SConscript +++ b/selfdrive/modeld/SConscript @@ -26,6 +26,10 @@ for pathdef, fn in {'TRANSFORM': 'transforms/transform.cl', 'LOADYUV': 'transfor xenv['CXXFLAGS'].append(f'-D{pathdef}_PATH=\\"{File(fn).abspath}\\"') # Compile cython +snpe_rpath_qcom = "/data/pythonpath/third_party/snpe/larch64" +snpe_rpath_pc = f"{Dir('#').abspath}/third_party/snpe/x86_64-linux-clang" +snpe_rpath = lenvCython['RPATH'] + [snpe_rpath_qcom if arch == "larch64" else snpe_rpath_pc] + cython_libs = envCython["LIBS"] + libs commonmodel_lib = lenv.Library('commonmodel', common_src) lenvCython.Program('models/commonmodel_pyx.so', 'models/commonmodel_pyx.pyx', LIBS=[commonmodel_lib, *cython_libs], FRAMEWORKS=frameworks) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index beb0d22ef5..bf74c2d1a0 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -16,6 +16,7 @@ class ModelConstants: MODEL_FREQ = 20 FEATURE_LEN = 512 FULL_HISTORY_BUFFER_LEN = 99 + HISTORY_BUFFER_LEN = 24 DESIRE_LEN = 8 TRAFFIC_CONVENTION_LEN = 2 LAT_PLANNER_STATE_LEN = 4 @@ -72,13 +73,14 @@ class Plan: class Meta: ENGAGED = slice(0, 1) # next 2, 4, 6, 8, 10 seconds - GAS_DISENGAGE = slice(1, 36, 7) - BRAKE_DISENGAGE = slice(2, 36, 7) - STEER_OVERRIDE = slice(3, 36, 7) - HARD_BRAKE_3 = slice(4, 36, 7) - HARD_BRAKE_4 = slice(5, 36, 7) - HARD_BRAKE_5 = slice(6, 36, 7) - GAS_PRESS = slice(7, 36, 7) + GAS_DISENGAGE = slice(1, 31, 6) + BRAKE_DISENGAGE = slice(2, 31, 6) + STEER_OVERRIDE = slice(3, 31, 6) + HARD_BRAKE_3 = slice(4, 31, 6) + HARD_BRAKE_4 = slice(5, 31, 6) + HARD_BRAKE_5 = slice(6, 31, 6) # next 0, 2, 4, 6, 8, 10 seconds - LEFT_BLINKER = slice(36, 48, 2) - RIGHT_BLINKER = slice(37, 48, 2) + GAS_PRESS = slice(31, 55, 4) + BRAKE_PRESS = slice(32, 55, 4) + LEFT_BLINKER = slice(33, 55, 4) + RIGHT_BLINKER = slice(34, 55, 4) diff --git a/selfdrive/modeld/fill_model_msg.py b/selfdrive/modeld/fill_model_msg.py index 3056da9374..a13d632aa6 100644 --- a/selfdrive/modeld/fill_model_msg.py +++ b/selfdrive/modeld/fill_model_msg.py @@ -3,11 +3,21 @@ import capnp import numpy as np from cereal import log from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta +from openpilot.selfdrive.controls.lib.drive_helpers import MIN_SPEED SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') ConfidenceClass = log.ModelDataV2.ConfidenceClass +def curv_from_psis(psi_target, psi_rate, vego, delay): + vego = np.clip(vego, MIN_SPEED, np.inf) + curv_from_psi = psi_target / (vego * delay) # epsilon to prevent divide-by-zero + return 2*curv_from_psi - psi_rate / vego + +def get_curvature_from_plan(plan, vego, delay): + psi_target = np.interp(delay, ModelConstants.T_IDXS, plan[:, Plan.T_FROM_CURRENT_EULER][:, 2]) + psi_rate = plan[:, Plan.ORIENTATION_RATE][0, 2] + return curv_from_psis(psi_target, psi_rate, vego, delay) class PublishState: def __init__(self): @@ -65,6 +75,8 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D extended_msg.valid = valid base_msg.valid = valid + desired_curv = float(get_curvature_from_plan(net_output_data['plan'][0], v_ego, delay)) + driving_model_data = base_msg.drivingModelData driving_model_data.frameId = vipc_frame_id @@ -73,7 +85,7 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D driving_model_data.modelExecutionTime = model_execution_time action = driving_model_data.action - action.desiredCurvature = float(net_output_data['desired_curvature'][0,0]) + action.desiredCurvature = desired_curv modelV2 = extended_msg.modelV2 modelV2.frameId = vipc_frame_id @@ -108,7 +120,7 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D # lateral planning action = modelV2.action - action.desiredCurvature = float(net_output_data['desired_curvature'][0,0]) + action.desiredCurvature = desired_curv # times at X_IDXS according to model plan PLAN_T_IDXS = [np.nan] * ModelConstants.IDX_N @@ -169,8 +181,8 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D disengage_predictions.brake3MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_3].tolist() disengage_predictions.brake4MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_4].tolist() disengage_predictions.brake5MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_5].tolist() - #disengage_predictions.gasPressProbs = net_output_data['meta'][0,Meta.GAS_PRESS].tolist() - #disengage_predictions.brakePressProbs = net_output_data['meta'][0,Meta.BRAKE_PRESS].tolist() + disengage_predictions.gasPressProbs = net_output_data['meta'][0,Meta.GAS_PRESS].tolist() + disengage_predictions.brakePressProbs = net_output_data['meta'][0,Meta.BRAKE_PRESS].tolist() publish_state.prev_brake_5ms2_probs[:-1] = publish_state.prev_brake_5ms2_probs[1:] publish_state.prev_brake_5ms2_probs[-1] = net_output_data['meta'][0,Meta.HARD_BRAKE_5][0] diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index 5783f6aa8e..49f8c483f0 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -59,14 +59,14 @@ class ModelState: def __init__(self, context: CLContext): self.frames = {'input_imgs': DrivingModelFrame(context), 'big_input_imgs': DrivingModelFrame(context)} self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) + self.full_features_20Hz = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) + self.desire_20Hz = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN + 1, ModelConstants.DESIRE_LEN), dtype=np.float32) # img buffers are managed in openCL transform code self.numpy_inputs = { - 'desire': np.zeros((1, (ModelConstants.FULL_HISTORY_BUFFER_LEN+1), ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire': np.zeros((1, (ModelConstants.HISTORY_BUFFER_LEN+1), ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), - 'lateral_control_params': np.zeros((1, ModelConstants.LATERAL_CONTROL_PARAMS_LEN), dtype=np.float32), - 'prev_desired_curv': np.zeros((1, (ModelConstants.FULL_HISTORY_BUFFER_LEN+1), ModelConstants.PREV_DESIRED_CURV_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), + 'features_buffer': np.zeros((1, ModelConstants.HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } with open(METADATA_PATH, 'rb') as f: @@ -98,11 +98,11 @@ class ModelState: new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) self.prev_desire[:] = inputs['desire'] - self.numpy_inputs['desire'][0,:-1] = self.numpy_inputs['desire'][0,1:] - self.numpy_inputs['desire'][0,-1] = new_desire + self.desire_20Hz[:-1] = self.desire_20Hz[1:] + self.desire_20Hz[-1] = new_desire + self.numpy_inputs['desire'][:] = self.desire_20Hz.reshape((1,25,4,-1)).max(axis=2) self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] - self.numpy_inputs['lateral_control_params'][:] = inputs['lateral_control_params'] imgs_cl = {'input_imgs': self.frames['input_imgs'].prepare(buf, transform.flatten()), 'big_input_imgs': self.frames['big_input_imgs'].prepare(wbuf, transform_wide.flatten())} @@ -113,7 +113,7 @@ class ModelState: self.tensor_inputs[key] = qcom_tensor_from_opencl_address(imgs_cl[key].mem_address, self.input_shapes[key], dtype=dtypes.uint8) else: for key in imgs_cl: - self.numpy_inputs[key] = self.frames[key].buffer_from_cl(imgs_cl[key]).reshape(self.input_shapes[key]).astype(dtype=np.float32) + self.numpy_inputs[key] = self.frames[key].buffer_from_cl(imgs_cl[key]).reshape(self.input_shapes[key]) if prepare_only: return None @@ -125,13 +125,11 @@ class ModelState: outputs = self.parser.parse_outputs(self.slice_outputs(self.output)) - self.numpy_inputs['features_buffer'][0,:-1] = self.numpy_inputs['features_buffer'][0,1:] - self.numpy_inputs['features_buffer'][0,-1] = outputs['hidden_state'][0, :] + self.full_features_20Hz[:-1] = self.full_features_20Hz[1:] + self.full_features_20Hz[-1] = outputs['hidden_state'][0, :] - - # TODO model only uses last value now - self.numpy_inputs['prev_desired_curv'][0,:-1] = self.numpy_inputs['prev_desired_curv'][0,1:] - self.numpy_inputs['prev_desired_curv'][0,-1,:] = outputs['desired_curvature'][0, :] + idxs = np.arange(-4,-100,-4)[::-1] + self.numpy_inputs['features_buffer'][:] = self.full_features_20Hz[idxs] return outputs @@ -242,7 +240,6 @@ def main(demo=False): is_rhd = sm["driverMonitoringState"].isRHD frame_id = sm["roadCameraState"].frameId v_ego = max(sm["carState"].vEgo, 0.) - lateral_control_params = np.array([v_ego, steer_delay], dtype=np.float32) if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']: device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32) dc = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))] @@ -273,7 +270,6 @@ def main(demo=False): inputs:dict[str, np.ndarray] = { 'desire': vec_desire, 'traffic_convention': traffic_convention, - 'lateral_control_params': lateral_control_params, } mt1 = time.perf_counter() diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc index 9973d18588..ad2620c7b4 100644 --- a/selfdrive/modeld/models/commonmodel.cc +++ b/selfdrive/modeld/models/commonmodel.cc @@ -8,8 +8,8 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { input_frames = std::make_unique(buf_size); input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); - img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 2*frame_size_bytes, NULL, &err)); - region.origin = 1 * frame_size_bytes; + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, 5*frame_size_bytes, NULL, &err)); + region.origin = 4 * frame_size_bytes; region.size = frame_size_bytes; last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); @@ -20,7 +20,7 @@ DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context) cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 4; i++) { CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); } loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); diff --git a/selfdrive/modeld/models/supercombo.onnx b/selfdrive/modeld/models/supercombo.onnx index 2e1a60a23e..777aa8aa7e 100644 --- a/selfdrive/modeld/models/supercombo.onnx +++ b/selfdrive/modeld/models/supercombo.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39786068cae1ed8c0dc34ef80c281dfcc67ed18a50e06b90765c49bcfdbf7db4 -size 51453312 +oid sha256:72d3d6f8d3c98f5431ec86be77b6350d7d4f43c25075c0106f1d1e7ec7c77668 +size 49096168 diff --git a/selfdrive/modeld/parse_model_outputs.py b/selfdrive/modeld/parse_model_outputs.py index 4367e9db8a..b699c5fd13 100644 --- a/selfdrive/modeld/parse_model_outputs.py +++ b/selfdrive/modeld/parse_model_outputs.py @@ -96,8 +96,6 @@ class Parser: out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH)) if 'lat_planner_solution' in outs: self.parse_mdn('lat_planner_solution', outs, in_N=0, out_N=0, out_shape=(ModelConstants.IDX_N,ModelConstants.LAT_PLANNER_SOLUTION_WIDTH)) - if 'desired_curvature' in outs: - self.parse_mdn('desired_curvature', outs, in_N=0, out_N=0, out_shape=(ModelConstants.DESIRED_CURV_WIDTH,)) for k in ['lead_prob', 'lane_lines_prob', 'meta']: self.parse_binary_crossentropy(k, outs) self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,)) diff --git a/selfdrive/modeld/tests/snpe_benchmark/.gitignore b/selfdrive/modeld/tests/snpe_benchmark/.gitignore new file mode 100644 index 0000000000..d83a1b2ff5 --- /dev/null +++ b/selfdrive/modeld/tests/snpe_benchmark/.gitignore @@ -0,0 +1 @@ +benchmark diff --git a/selfdrive/modeld/tests/snpe_benchmark/benchmark.cc b/selfdrive/modeld/tests/snpe_benchmark/benchmark.cc new file mode 100644 index 0000000000..f72f7fb1a7 --- /dev/null +++ b/selfdrive/modeld/tests/snpe_benchmark/benchmark.cc @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p) { + return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) - ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec); +} + +void PrintErrorStringAndExit() { + cout << "ERROR!" << endl; + const char* const errStr = zdl::DlSystem::getLastErrorString(); + std::cerr << errStr << std::endl; + std::exit(EXIT_FAILURE); +} + + +zdl::DlSystem::Runtime_t checkRuntime() { + static zdl::DlSystem::Version_t Version = zdl::SNPE::SNPEFactory::getLibraryVersion(); + static zdl::DlSystem::Runtime_t Runtime; + std::cout << "SNPE Version: " << Version.asString().c_str() << std::endl; //Print Version number + if (zdl::SNPE::SNPEFactory::isRuntimeAvailable(zdl::DlSystem::Runtime_t::DSP)) { + std::cout << "Using DSP runtime" << std::endl; + Runtime = zdl::DlSystem::Runtime_t::DSP; + } else if (zdl::SNPE::SNPEFactory::isRuntimeAvailable(zdl::DlSystem::Runtime_t::GPU)) { + std::cout << "Using GPU runtime" << std::endl; + Runtime = zdl::DlSystem::Runtime_t::GPU; + } else { + std::cout << "Using cpu runtime" << std::endl; + Runtime = zdl::DlSystem::Runtime_t::CPU; + } + return Runtime; +} + +void test(char *filename) { + static zdl::DlSystem::Runtime_t runtime = checkRuntime(); + std::unique_ptr container; + container = zdl::DlContainer::IDlContainer::open(filename); + + if (!container) { PrintErrorStringAndExit(); } + cout << "start build" << endl; + std::unique_ptr snpe; + { + snpe = NULL; + zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); + snpe = snpeBuilder.setOutputLayers({}) + .setRuntimeProcessor(runtime) + .setUseUserSuppliedBuffers(false) + //.setDebugMode(true) + .build(); + if (!snpe) { + cout << "ERROR!" << endl; + const char* const errStr = zdl::DlSystem::getLastErrorString(); + std::cerr << errStr << std::endl; + } + cout << "ran snpeBuilder" << endl; + } + + const auto &strList_opt = snpe->getInputTensorNames(); + if (!strList_opt) throw std::runtime_error("Error obtaining input tensor names"); + + cout << "get input tensor names done" << endl; + const auto &strList = *strList_opt; + static zdl::DlSystem::TensorMap inputTensorMap; + static zdl::DlSystem::TensorMap outputTensorMap; + vector > inputs; + for (int i = 0; i < strList.size(); i++) { + cout << "input name: " << strList.at(i) << endl; + + const auto &inputDims_opt = snpe->getInputDimensions(strList.at(i)); + const auto &inputShape = *inputDims_opt; + inputs.push_back(zdl::SNPE::SNPEFactory::getTensorFactory().createTensor(inputShape)); + inputTensorMap.add(strList.at(i), inputs[i].get()); + } + + struct timespec start, end; + cout << "**** starting benchmark ****" << endl; + for (int i = 0; i < 50; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + int err = snpe->execute(inputTensorMap, outputTensorMap); + assert(err == true); + clock_gettime(CLOCK_MONOTONIC, &end); + uint64_t timeElapsed = timespecDiff(&end, &start); + printf("time: %f ms\n", timeElapsed*1.0/1e6); + } +} + +void get_testframe(int index, std::unique_ptr &input) { + FILE * pFile; + string filepath="/data/ipt/quantize_samples/sample_input_"+std::to_string(index); + pFile = fopen(filepath.c_str(), "rb"); + int length = 1*6*160*320*4; + float * frame_buffer = new float[length/4]; // 32/8 + fread(frame_buffer, length, 1, pFile); + // std::cout << *(frame_buffer+length/4-1) << std::endl; + std::copy(frame_buffer, frame_buffer+(length/4), input->begin()); + fclose(pFile); +} + +void SaveITensor(const std::string& path, const zdl::DlSystem::ITensor* tensor) +{ + std::ofstream os(path, std::ofstream::binary); + if (!os) + { + std::cerr << "Failed to open output file for writing: " << path << "\n"; + std::exit(EXIT_FAILURE); + } + for ( auto it = tensor->cbegin(); it != tensor->cend(); ++it ) + { + float f = *it; + if (!os.write(reinterpret_cast(&f), sizeof(float))) + { + std::cerr << "Failed to write data to: " << path << "\n"; + std::exit(EXIT_FAILURE); + } + } +} + +void testrun(char* modelfile) { + static zdl::DlSystem::Runtime_t runtime = checkRuntime(); + std::unique_ptr container; + container = zdl::DlContainer::IDlContainer::open(modelfile); + + if (!container) { PrintErrorStringAndExit(); } + cout << "start build" << endl; + std::unique_ptr snpe; + { + snpe = NULL; + zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); + snpe = snpeBuilder.setOutputLayers({}) + .setRuntimeProcessor(runtime) + .setUseUserSuppliedBuffers(false) + //.setDebugMode(true) + .build(); + if (!snpe) { + cout << "ERROR!" << endl; + const char* const errStr = zdl::DlSystem::getLastErrorString(); + std::cerr << errStr << std::endl; + } + cout << "ran snpeBuilder" << endl; + } + + const auto &strList_opt = snpe->getInputTensorNames(); + if (!strList_opt) throw std::runtime_error("Error obtaining input tensor names"); + cout << "get input tensor names done" << endl; + + const auto &strList = *strList_opt; + static zdl::DlSystem::TensorMap inputTensorMap; + static zdl::DlSystem::TensorMap outputTensorMap; + + assert(strList.size() == 1); + const auto &inputDims_opt = snpe->getInputDimensions(strList.at(0)); + const auto &inputShape = *inputDims_opt; + std::cout << "winkwink" << std::endl; + + for (int i=0; i<10000; i++) { + std::unique_ptr input; + input = zdl::SNPE::SNPEFactory::getTensorFactory().createTensor(inputShape); + get_testframe(i, input); + snpe->execute(input.get(), outputTensorMap); + zdl::DlSystem::StringList tensorNames = outputTensorMap.getTensorNames(); + std::for_each(tensorNames.begin(), tensorNames.end(), [&](const char* name) { + std::ostringstream path; + path << "/data/opt/Result_" << std::to_string(i) << ".raw"; + auto tensorPtr = outputTensorMap.getTensor(name); + SaveITensor(path.str(), tensorPtr); + }); + } +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + if (argc == 2) { + while (true) test(argv[1]); + } else if (argc == 3) { + testrun(argv[1]); + } + return 0; +} + diff --git a/selfdrive/modeld/tests/snpe_benchmark/benchmark.sh b/selfdrive/modeld/tests/snpe_benchmark/benchmark.sh new file mode 100755 index 0000000000..a9d3f79786 --- /dev/null +++ b/selfdrive/modeld/tests/snpe_benchmark/benchmark.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e +clang++ -I /data/openpilot/third_party/snpe/include/ -L/data/pythonpath/third_party/snpe/aarch64 -lSNPE benchmark.cc -o benchmark +export LD_LIBRARY_PATH="/data/pythonpath/third_party/snpe/aarch64/:$HOME/openpilot/third_party/snpe/x86_64/:$LD_LIBRARY_PATH" +exec ./benchmark $1 diff --git a/selfdrive/test/ciui.py b/selfdrive/test/ciui.py new file mode 100755 index 0000000000..f3b0c1a98f --- /dev/null +++ b/selfdrive/test/ciui.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +import signal +import subprocess + +signal.signal(signal.SIGINT, signal.SIG_DFL) +signal.signal(signal.SIGTERM, signal.SIG_DFL) + +from PyQt5.QtCore import QTimer +from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel +from openpilot.selfdrive.ui.qt.python_helpers import set_main_window + +class Window(QWidget): + def __init__(self, parent=None): + super().__init__(parent) + + layout = QVBoxLayout() + self.setLayout(layout) + + self.l = QLabel("jenkins runner") + layout.addWidget(self.l) + layout.addStretch(1) + layout.setContentsMargins(20, 20, 20, 20) + + cmds = [ + "cat /etc/hostname", + "echo AGNOS v$(cat /VERSION)", + "uptime -p", + ] + self.labels = {} + for c in cmds: + self.labels[c] = QLabel(c) + layout.addWidget(self.labels[c]) + + self.setStyleSheet(""" + * { + color: white; + font-size: 55px; + background-color: black; + font-family: "JetBrains Mono"; + } + """) + + self.timer = QTimer() + self.timer.timeout.connect(self.update) + self.timer.start(10 * 1000) + self.update() + + def update(self): + for cmd, label in self.labels.items(): + out = subprocess.run(cmd, capture_output=True, + shell=True, check=False, encoding='utf8').stdout + label.setText(out.strip()) + +if __name__ == "__main__": + app = QApplication([]) + w = Window() + set_main_window(w) + app.exec_() diff --git a/selfdrive/test/docker_tag_multiarch.sh b/selfdrive/test/docker_tag_multiarch.sh new file mode 100755 index 0000000000..c1761802c7 --- /dev/null +++ b/selfdrive/test/docker_tag_multiarch.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -e + +if [ $# -lt 2 ]; then + echo "Usage: $0 ..." + exit 1 +fi + +SCRIPT_DIR=$(dirname "$0") +ARCHS=("${@:2}") + +source $SCRIPT_DIR/docker_common.sh $1 + +MANIFEST_AMENDS="" +for ARCH in ${ARCHS[@]}; do + MANIFEST_AMENDS="$MANIFEST_AMENDS --amend $REMOTE_TAG-$ARCH:$COMMIT_SHA" +done + +docker manifest create $REMOTE_TAG $MANIFEST_AMENDS +docker manifest create $REMOTE_SHA_TAG $MANIFEST_AMENDS + +if [[ -n "$PUSH_IMAGE" ]]; then + docker manifest push $REMOTE_TAG + docker manifest push $REMOTE_SHA_TAG +fi diff --git a/selfdrive/test/loop_until_fail.sh b/selfdrive/test/loop_until_fail.sh new file mode 100755 index 0000000000..b73009dba6 --- /dev/null +++ b/selfdrive/test/loop_until_fail.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -e + +# Loop something forever until it fails, for verifying new tests + +while true; do + $@ +done diff --git a/selfdrive/test/process_replay/imgproc_replay_ref_hash b/selfdrive/test/process_replay/imgproc_replay_ref_hash new file mode 100644 index 0000000000..defcb3681c --- /dev/null +++ b/selfdrive/test/process_replay/imgproc_replay_ref_hash @@ -0,0 +1 @@ +707434c540e685bbe2886b3ff7c82fd61939d362 \ No newline at end of file diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py index f406b79e10..94803643e0 100755 --- a/selfdrive/test/process_replay/model_replay.py +++ b/selfdrive/test/process_replay/model_replay.py @@ -57,7 +57,7 @@ def generate_report(proposed, master, tmp, commit): (lambda x: x.action.desiredCurvature, "desiredCurvature"), (lambda x: x.leadsV3[0].x[0], "leadsV3.x"), (lambda x: x.laneLines[1].y[0], "laneLines.y"), - #(lambda x: x.meta.disengagePredictions.gasPressProbs[1], "gasPressProbs") + (lambda x: x.meta.disengagePredictions.gasPressProbs[1], "gasPressProbs") ], "modelV2") DriverStateV2_Plots = zl([ (lambda x: x.wheelOnRightProb, "wheelOnRightProb"), diff --git a/selfdrive/test/process_replay/test_imgproc.py b/selfdrive/test/process_replay/test_imgproc.py new file mode 100644 index 0000000000..27d0541a50 --- /dev/null +++ b/selfdrive/test/process_replay/test_imgproc.py @@ -0,0 +1,98 @@ +import os +import numpy as np +import hashlib + +import pyopencl as cl # install with `PYOPENCL_CL_PRETEND_VERSION=2.0 pip install pyopencl` + +from openpilot.system.hardware import PC, TICI +from openpilot.common.basedir import BASEDIR +from openpilot.common.transformations.camera import DEVICE_CAMERAS +from openpilot.system.camerad.snapshot.snapshot import yuv_to_rgb +from openpilot.tools.lib.logreader import LogReader + +# TODO: check all sensors +TEST_ROUTE = "8345e3b82948d454|2022-05-04--13-45-33/0" + +cam = DEVICE_CAMERAS[("tici", "ar0231")] +FRAME_WIDTH, FRAME_HEIGHT = (cam.dcam.width, cam.dcam.height) +FRAME_STRIDE = FRAME_WIDTH * 12 // 8 + 4 + +UV_WIDTH = FRAME_WIDTH // 2 +UV_HEIGHT = FRAME_HEIGHT // 2 +UV_SIZE = UV_WIDTH * UV_HEIGHT + + +def init_kernels(frame_offset=0): + ctx = cl.create_some_context(interactive=False) + + with open(os.path.join(BASEDIR, 'system/camerad/cameras/process_raw.cl')) as f: + build_args = f' -cl-fast-relaxed-math -cl-denorms-are-zero -cl-single-precision-constant -I{BASEDIR}/system/camerad/sensors ' + \ + f' -DFRAME_WIDTH={FRAME_WIDTH} -DFRAME_HEIGHT={FRAME_WIDTH} -DFRAME_STRIDE={FRAME_STRIDE} -DFRAME_OFFSET={frame_offset} ' + \ + f' -DRGB_WIDTH={FRAME_WIDTH} -DRGB_HEIGHT={FRAME_HEIGHT} -DYUV_STRIDE={FRAME_WIDTH} -DUV_OFFSET={FRAME_WIDTH*FRAME_HEIGHT}' + \ + ' -DSENSOR_ID=1 -DVIGNETTING=0 ' + if PC: + build_args += ' -DHALF_AS_FLOAT=1 -cl-std=CL2.0' + imgproc_prg = cl.Program(ctx, f.read()).build(options=build_args) + + return ctx, imgproc_prg + +def proc_frame(ctx, imgproc_prg, data, rgb=False): + q = cl.CommandQueue(ctx) + + yuv_buff = np.empty(FRAME_WIDTH * FRAME_HEIGHT + UV_SIZE * 2, dtype=np.uint8) + + cam_g = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=data) + yuv_g = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, FRAME_WIDTH * FRAME_HEIGHT + UV_SIZE * 2) + + krn = imgproc_prg.process_raw + krn.set_scalar_arg_dtypes([None, None, np.int32]) + local_worksize = (20, 20) if TICI else (4, 4) + + ev1 = krn(q, (FRAME_WIDTH//2, FRAME_HEIGHT//2), local_worksize, cam_g, yuv_g, 1) + cl.enqueue_copy(q, yuv_buff, yuv_g, wait_for=[ev1]).wait() + cl.enqueue_barrier(q) + + y = yuv_buff[:FRAME_WIDTH*FRAME_HEIGHT].reshape((FRAME_HEIGHT, FRAME_WIDTH)) + u = yuv_buff[FRAME_WIDTH*FRAME_HEIGHT::2].reshape((UV_HEIGHT, UV_WIDTH)) + v = yuv_buff[FRAME_WIDTH*FRAME_HEIGHT+1::2].reshape((UV_HEIGHT, UV_WIDTH)) + + if rgb: + return yuv_to_rgb(y, u, v) + else: + return y, u, v + + +def imgproc_replay(lr): + ctx, imgproc_prg = init_kernels() + + frames = [] + for m in lr: + if m.which() == 'roadCameraState': + cs = m.roadCameraState + if cs.image: + data = np.frombuffer(cs.image, dtype=np.uint8) + img = proc_frame(ctx, imgproc_prg, data) + + frames.append(img) + + return frames + + +if __name__ == "__main__": + # load logs + lr = list(LogReader(TEST_ROUTE)) + # run replay + out_frames = imgproc_replay(lr) + + all_pix = np.concatenate([np.concatenate([d.flatten() for d in f]) for f in out_frames]) + pix_hash = hashlib.sha1(all_pix).hexdigest() + + with open('imgproc_replay_ref_hash') as f: + ref_hash = f.read() + + if pix_hash != ref_hash: + print("result changed! please check kernel") + print(f"ref: {ref_hash}") + print(f"new: {pix_hash}") + else: + print("test passed") diff --git a/selfdrive/test/profiling/.gitignore b/selfdrive/test/profiling/.gitignore new file mode 100644 index 0000000000..76acac7f93 --- /dev/null +++ b/selfdrive/test/profiling/.gitignore @@ -0,0 +1,2 @@ +cachegrind.out.* +*.prof diff --git a/selfdrive/test/profiling/__init__.py b/selfdrive/test/profiling/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/test/profiling/lib.py b/selfdrive/test/profiling/lib.py new file mode 100644 index 0000000000..62bb305ca8 --- /dev/null +++ b/selfdrive/test/profiling/lib.py @@ -0,0 +1,91 @@ +from collections import defaultdict +from cereal.services import SERVICE_LIST +import cereal.messaging as messaging +import capnp + + +class ReplayDone(Exception): + pass + + +class SubSocket: + def __init__(self, msgs, trigger): + self.i = 0 + self.trigger = trigger + self.msgs = [m.as_builder().to_bytes() for m in msgs if m.which() == trigger] + self.max_i = len(self.msgs) - 1 + + def receive(self, non_blocking=False): + if non_blocking: + return None + + if self.i == self.max_i: + raise ReplayDone + + while True: + msg = self.msgs[self.i] + self.i += 1 + return msg + + +class PubSocket: + def send(self, data): + pass + + +class SubMaster(messaging.SubMaster): + def __init__(self, msgs, trigger, services, check_averag_freq=False): + self.frame = 0 + self.data = {} + self.ignore_alive = [] + + self.alive = {s: True for s in services} + self.updated = {s: False for s in services} + self.rcv_time = {s: 0. for s in services} + self.rcv_frame = {s: 0 for s in services} + self.valid = {s: True for s in services} + self.freq_ok = {s: True for s in services} + self.freq_tracker = {s: messaging.FrequencyTracker(SERVICE_LIST[s].frequency, SERVICE_LIST[s].frequency, False) for s in services} + self.logMonoTime = {} + self.sock = {} + self.freq = {} + self.check_average_freq = check_averag_freq + self.non_polled_services = [] + self.ignore_average_freq = [] + + # TODO: specify multiple triggers for service like plannerd that poll on more than one service + cur_msgs = [] + self.msgs = [] + msgs = [m for m in msgs if m.which() in services] + + for msg in msgs: + cur_msgs.append(msg) + if msg.which() == trigger: + self.msgs.append(cur_msgs) + cur_msgs = [] + + self.msgs = list(reversed(self.msgs)) + + for s in services: + self.freq[s] = SERVICE_LIST[s].frequency + try: + data = messaging.new_message(s) + except capnp.lib.capnp.KjException: + # lists + data = messaging.new_message(s, 0) + + self.data[s] = getattr(data, s) + self.logMonoTime[s] = 0 + self.sock[s] = SubSocket(msgs, s) + + def update(self, timeout=None): + if not len(self.msgs): + raise ReplayDone + + cur_msgs = self.msgs.pop() + self.update_msgs(cur_msgs[0].logMonoTime, self.msgs.pop()) + + +class PubMaster(messaging.PubMaster): + def __init__(self): + self.sock = defaultdict(PubSocket) diff --git a/selfdrive/test/profiling/profiler.py b/selfdrive/test/profiling/profiler.py new file mode 100755 index 0000000000..d50b157a37 --- /dev/null +++ b/selfdrive/test/profiling/profiler.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +import os +import sys +import cProfile +import pprofile +import pyprof2calltree + +from opendbc.car.toyota.values import CAR as TOYOTA +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.volkswagen.values import CAR as VW +from openpilot.common.params import Params +from openpilot.tools.lib.logreader import LogReader +from openpilot.selfdrive.test.profiling.lib import SubMaster, PubMaster, SubSocket, ReplayDone +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS + +BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/" + +CARS = { + 'toyota': ("0982d79ebb0de295|2021-01-03--20-03-36/6", TOYOTA.TOYOTA_RAV4), + 'honda': ("0982d79ebb0de295|2021-01-08--10-13-10/6", HONDA.HONDA_CIVIC), + "vw": ("ef895f46af5fd73f|2021-05-22--14-06-35/6", VW.AUDI_A3_MK3), +} + + +def get_inputs(msgs, process, fingerprint): + for config in CONFIGS: + if config.proc_name == process: + sub_socks = list(config.pubs) + trigger = sub_socks[0] + break + + # some procs block on CarParams + for msg in msgs: + if msg.which() == 'carParams': + m = msg.as_builder() + m.carParams.carFingerprint = fingerprint + Params().put("CarParams", m.carParams.copy().to_bytes()) + break + + sm = SubMaster(msgs, trigger, sub_socks) + pm = PubMaster() + if 'can' in sub_socks: + can_sock = SubSocket(msgs, 'can') + else: + can_sock = None + return sm, pm, can_sock + + +def profile(proc, func, car='toyota'): + segment, fingerprint = CARS[car] + segment = segment.replace('|', '/') + rlog_url = f"{BASE_URL}{segment}/rlog.bz2" + msgs = list(LogReader(rlog_url)) * int(os.getenv("LOOP", "1")) + + os.environ['FINGERPRINT'] = fingerprint + os.environ['SKIP_FW_QUERY'] = "1" + os.environ['REPLAY'] = "1" + + def run(sm, pm, can_sock): + try: + if can_sock is not None: + func(sm, pm, can_sock) + else: + func(sm, pm) + except ReplayDone: + pass + + # Statistical + sm, pm, can_sock = get_inputs(msgs, proc, fingerprint) + with pprofile.StatisticalProfile()(period=0.00001) as pr: + run(sm, pm, can_sock) + pr.dump_stats(f'cachegrind.out.{proc}_statistical') + + # Deterministic + sm, pm, can_sock = get_inputs(msgs, proc, fingerprint) + with cProfile.Profile() as pr: + run(sm, pm, can_sock) + pyprof2calltree.convert(pr.getstats(), f'cachegrind.out.{proc}_deterministic') + + +if __name__ == '__main__': + from openpilot.selfdrive.controls.controlsd import main as controlsd_thread + from openpilot.selfdrive.locationd.paramsd import main as paramsd_thread + from openpilot.selfdrive.controls.plannerd import main as plannerd_thread + + procs = { + 'controlsd': controlsd_thread, + 'paramsd': paramsd_thread, + 'plannerd': plannerd_thread, + } + + proc = sys.argv[1] + if proc not in procs: + print(f"{proc} not available") + sys.exit(0) + else: + profile(proc, procs[proc]) diff --git a/system/athena/registration.py b/system/athena/registration.py index 964fbff51e..a1e8605a9d 100755 --- a/system/athena/registration.py +++ b/system/athena/registration.py @@ -33,17 +33,20 @@ def register(show_spinner=False) -> str | None: """ params = Params() + IMEI = params.get("IMEI", encoding='utf8') + HardwareSerial = params.get("HardwareSerial", encoding='utf8') dongle_id: str | None = params.get("DongleId", encoding='utf8') if dongle_id is None and Path(Paths.persist_root()+"/comma/dongle_id").is_file(): # not all devices will have this; added early in comma 3X production (2/28/24) with open(Paths.persist_root()+"/comma/dongle_id") as f: dongle_id = f.read().strip() + needs_registration = None in (IMEI, HardwareSerial, dongle_id) pubkey = Path(Paths.persist_root()+"/comma/id_rsa.pub") if not pubkey.is_file(): dongle_id = UNREGISTERED_DONGLE_ID cloudlog.warning(f"missing public key: {pubkey}") - elif dongle_id is None: + elif needs_registration: if show_spinner: spinner = Spinner() spinner.update("registering device") @@ -68,6 +71,9 @@ def register(show_spinner=False) -> str | None: if time.monotonic() - start_time > 60 and show_spinner: spinner.update(f"registering device - serial: {serial}, IMEI: ({imei1}, {imei2})") + params.put("IMEI", imei1) + params.put("HardwareSerial", serial) + backoff = 0 start_time = time.monotonic() while True: diff --git a/system/athena/tests/test_registration.py b/system/athena/tests/test_registration.py index c1dabb78ec..17ebaa472d 100644 --- a/system/athena/tests/test_registration.py +++ b/system/athena/tests/test_registration.py @@ -32,6 +32,8 @@ class TestRegistration: def test_valid_cache(self, mocker): # if all params are written, return the cached dongle id. # should work with a dongle ID on either /persist/ or normal params + self.params.put("IMEI", "imei") + self.params.put("HardwareSerial", "serial") self._generate_keys() dongle = "DONGLE_ID_123" diff --git a/system/hardware/tici/hardware.h b/system/hardware/tici/hardware.h index fcfb07830a..20ee88de80 100644 --- a/system/hardware/tici/hardware.h +++ b/system/hardware/tici/hardware.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -23,7 +22,7 @@ public: static std::string get_name() { std::string model = util::read_file("/sys/firmware/devicetree/base/model"); - return util::strip(model.substr(std::string("comma ").size())); + return model.substr(std::string("comma ").size()); } static cereal::InitData::DeviceType get_device_type() { @@ -33,8 +32,7 @@ public: {"mici", cereal::InitData::DeviceType::MICI} }; auto it = device_map.find(get_name()); - assert(it != device_map.end()); - return it->second; + return it != device_map.end() ? it->second : cereal::InitData::DeviceType::UNKNOWN; } static int get_voltage() { return std::atoi(util::read_file("/sys/class/hwmon/hwmon1/in1_input").c_str()); } @@ -84,17 +82,17 @@ public: return; } - int value = util::map_val(std::clamp(percent, 0, 100), 0, 100, 0, 255); + percent = std::clamp(percent, 0, 100); std::ofstream torch_brightness("/sys/class/leds/led:torch_2/brightness"); if (torch_brightness.is_open()) { - torch_brightness << value << "\n"; + torch_brightness << percent << "\n"; torch_brightness.close(); } std::ofstream switch_brightness("/sys/class/leds/led:switch_2/brightness"); if (switch_brightness.is_open()) { - switch_brightness << value << "\n"; + switch_brightness << percent << "\n"; switch_brightness.close(); } } diff --git a/system/manager/manager.py b/system/manager/manager.py index 7a8ec9fc86..5cbc73b838 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -67,8 +67,7 @@ def manager_init() -> None: except PermissionError: print(f"WARNING: failed to make {Paths.shm_path()}") - # set params - serial = HARDWARE.get_serial() + # set version params params.put("Version", build_metadata.openpilot.version) params.put("TermsVersion", terms_version) params.put("TrainingVersion", training_version) @@ -78,13 +77,13 @@ def manager_init() -> None: params.put("GitRemote", build_metadata.openpilot.git_origin) params.put_bool("IsTestedBranch", build_metadata.tested_channel) params.put_bool("IsReleaseBranch", build_metadata.release_channel) - params.put("HardwareSerial", serial) # set dongle id reg_res = register(show_spinner=True) if reg_res: dongle_id = reg_res else: + serial = params.get("HardwareSerial") raise Exception(f"Registration failed for device {serial}") os.environ['DONGLE_ID'] = dongle_id # Needed for swaglog os.environ['GIT_ORIGIN'] = build_metadata.openpilot.git_normalized_origin # Needed for swaglog diff --git a/system/manager/process_config.py b/system/manager/process_config.py index e6767ae740..9712b63e01 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -79,8 +79,7 @@ def and_(*fns): procs = [ DaemonProcess("manage_athenad", "system.athena.manage_athenad", "AthenadPid"), - NativeProcess("camerad", "system/camerad", ["./camerad"], driverview, enabled=not WEBCAM), - PythonProcess("webcamerad", "tools.webcam.camerad", driverview, enabled=WEBCAM), + NativeProcess("camerad", "system/camerad", ["./camerad"], driverview), NativeProcess("logcatd", "system/logcatd", ["./logcatd"], only_onroad), NativeProcess("proclogd", "system/proclogd", ["./proclogd"], only_onroad), PythonProcess("logmessaged", "system.logmessaged", always_run), @@ -88,7 +87,7 @@ procs = [ PythonProcess("timed", "system.timed", always_run, enabled=not PC), # TODO Make python process once TG allows opening QCOM from child proc - NativeProcess("dmonitoringmodeld", "selfdrive/modeld", ["./dmonitoringmodeld"], driverview, enabled=(WEBCAM or not PC)), + NativeProcess("dmonitoringmodeld", "selfdrive/modeld", ["./dmonitoringmodeld"], driverview, enabled=(not PC or WEBCAM)), NativeProcess("encoderd", "system/loggerd", ["./encoderd"], only_onroad), NativeProcess("stream_encoderd", "system/loggerd", ["./encoderd", "--stream"], notcar), NativeProcess("loggerd", "system/loggerd", ["./loggerd"], logging), @@ -106,7 +105,7 @@ procs = [ PythonProcess("selfdrived", "selfdrive.selfdrived.selfdrived", only_onroad), PythonProcess("card", "selfdrive.car.card", only_onroad), PythonProcess("deleter", "system.loggerd.deleter", always_run), - PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(WEBCAM or not PC)), + PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(not PC or WEBCAM)), PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), PythonProcess("pandad", "selfdrive.pandad.pandad", always_run), PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad), diff --git a/system/timed.py b/system/timed.py index de9b0ffb59..3eb84353ad 100755 --- a/system/timed.py +++ b/system/timed.py @@ -13,7 +13,7 @@ from openpilot.common.gps import get_gps_location_service def set_time(new_time): diff = datetime.datetime.now() - new_time - if abs(diff) < datetime.timedelta(seconds=10): + if diff < datetime.timedelta(seconds=10): cloudlog.debug(f"Time diff too small: {diff}") return diff --git a/third_party/snpe/aarch64-ubuntu-gcc7.5/libPlatformValidatorShared.so b/third_party/snpe/aarch64-ubuntu-gcc7.5/libPlatformValidatorShared.so new file mode 100644 index 0000000000..a1c6fed910 --- /dev/null +++ b/third_party/snpe/aarch64-ubuntu-gcc7.5/libPlatformValidatorShared.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb3b1fd29d958e9a3a6625eac9fac9e7cd6eb40309b285ad973324761db0b4c9 +size 1202792 diff --git a/third_party/snpe/aarch64-ubuntu-gcc7.5/libSNPE.so b/third_party/snpe/aarch64-ubuntu-gcc7.5/libSNPE.so new file mode 100644 index 0000000000..54c0c32e41 --- /dev/null +++ b/third_party/snpe/aarch64-ubuntu-gcc7.5/libSNPE.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:161a5d0bf7347465b53ae49690a38fbacf03d606ef204147b3b148a5f59188da +size 9008016 diff --git a/third_party/snpe/aarch64-ubuntu-gcc7.5/libcalculator.so b/third_party/snpe/aarch64-ubuntu-gcc7.5/libcalculator.so new file mode 100644 index 0000000000..2154203026 --- /dev/null +++ b/third_party/snpe/aarch64-ubuntu-gcc7.5/libcalculator.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e0e66c12a1eb3b5b4b2b2694831ca51e5132818f400dad789adbcc30e0e0793 +size 14032 diff --git a/third_party/snpe/aarch64-ubuntu-gcc7.5/libhta.so b/third_party/snpe/aarch64-ubuntu-gcc7.5/libhta.so new file mode 100644 index 0000000000..1d81abd3a5 --- /dev/null +++ b/third_party/snpe/aarch64-ubuntu-gcc7.5/libhta.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:784f2e80fa3534cf7934c5ecbbda37db633104380f2b41d896b4721ad6006eb2 +size 2420312 diff --git a/third_party/snpe/aarch64-ubuntu-gcc7.5/libsnpe_dsp_domains_v2.so b/third_party/snpe/aarch64-ubuntu-gcc7.5/libsnpe_dsp_domains_v2.so new file mode 100644 index 0000000000..40e3d5af74 --- /dev/null +++ b/third_party/snpe/aarch64-ubuntu-gcc7.5/libsnpe_dsp_domains_v2.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33afe465e74bbe2c409350d2ca8e86cfadf050ceb8feac75a86adc19ff1f9c48 +size 26016 diff --git a/third_party/snpe/dsp/libcalculator_skel.so b/third_party/snpe/dsp/libcalculator_skel.so new file mode 100644 index 0000000000..9e9e9221be --- /dev/null +++ b/third_party/snpe/dsp/libcalculator_skel.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bee94d38195478ffdd0ce15292a2dfa7813377f4c3b7d99c270e05079d1746b +size 20828 diff --git a/third_party/snpe/dsp/libsnpe_dsp_v65_domains_v2_skel.so b/third_party/snpe/dsp/libsnpe_dsp_v65_domains_v2_skel.so new file mode 100644 index 0000000000..3f1b7a8b8c --- /dev/null +++ b/third_party/snpe/dsp/libsnpe_dsp_v65_domains_v2_skel.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e040c87072aa915c47859c8c7f74076b98c6919b83ddd5dc4bb555870d586a7 +size 1813866 diff --git a/third_party/snpe/dsp/libsnpe_dsp_v66_domains_v2_skel.so b/third_party/snpe/dsp/libsnpe_dsp_v66_domains_v2_skel.so new file mode 100644 index 0000000000..aa42b5e830 --- /dev/null +++ b/third_party/snpe/dsp/libsnpe_dsp_v66_domains_v2_skel.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:838bc58ac0094ba9593cf7c44ab6e8a94ae3dbbe176e320d9fbe86ceead53c5e +size 1817962 diff --git a/third_party/snpe/dsp/libsnpe_dsp_v68_domains_v3_skel.so b/third_party/snpe/dsp/libsnpe_dsp_v68_domains_v3_skel.so new file mode 100644 index 0000000000..9423da1b94 --- /dev/null +++ b/third_party/snpe/dsp/libsnpe_dsp_v68_domains_v3_skel.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77d025d59521e13e4ed012f0d9d2b684cdb858208d70426078df51219eaeb9bd +size 10098673 diff --git a/third_party/snpe/include/DiagLog/IDiagLog.hpp b/third_party/snpe/include/DiagLog/IDiagLog.hpp new file mode 100644 index 0000000000..018b567256 --- /dev/null +++ b/third_party/snpe/include/DiagLog/IDiagLog.hpp @@ -0,0 +1,84 @@ +//============================================================================= +// +// Copyright (c) 2015, 2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#ifndef __IDIAGLOG_HPP_ +#define __IDIAGLOG_HPP_ + +#include + +#include "DiagLog/Options.hpp" +#include "DlSystem/String.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl +{ +namespace DiagLog +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/// @brief . +/// +/// Interface for controlling logging for zdl components. + +class ZDL_EXPORT IDiagLog +{ +public: + + /// @brief . + /// + /// Sets the options after initialization occurs. + /// + /// @param[in] loggingOptions The options to set up diagnostic logging. + /// + /// @return False if the options could not be set. Ensure logging is not started. + virtual bool setOptions(const Options& loggingOptions) = 0; + + /// @brief . + /// + /// Gets the curent options for the diag logger. + /// + /// @return Diag log options object. + virtual Options getOptions() = 0; + + /// @brief . + /// + /// Allows for setting the log mask once diag logging has started + /// + /// @return True if the level was set successfully, false if a failure occurred. + virtual bool setDiagLogMask(const std::string& mask) = 0; + + /// @brief . + /// + /// Allows for setting the log mask once diag logging has started + /// + /// @return True if the level was set successfully, false if a failure occurred. + virtual bool setDiagLogMask(const zdl::DlSystem::String& mask) = 0; + + /// @brief . + /// + /// Enables logging for zdl components. + /// + /// Logging should be started prior to the instantiation of zdl components + /// to ensure all events are captured. + /// + /// @return False if diagnostic logging could not be started. + virtual bool start(void) = 0; + + /// @brief Disables logging for zdl components. + virtual bool stop(void) = 0; + + virtual ~IDiagLog() {}; +}; + +} // DiagLog namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif diff --git a/third_party/snpe/include/DiagLog/Options.hpp b/third_party/snpe/include/DiagLog/Options.hpp new file mode 100644 index 0000000000..798fa3f124 --- /dev/null +++ b/third_party/snpe/include/DiagLog/Options.hpp @@ -0,0 +1,79 @@ +//============================================================================= +// +// Copyright (c) 2015, 2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#ifndef __DIAGLOG_OPTIONS_HPP_ +#define __DIAGLOG_OPTIONS_HPP_ + +#include +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl +{ +namespace DiagLog +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/// @brief . +/// +/// Options for setting up diagnostic logging for zdl components. +class ZDL_EXPORT Options +{ +public: + Options() : + DiagLogMask(""), + LogFileDirectory("diaglogs"), + LogFileName("DiagLog"), + LogFileRotateCount(20), + LogFileReplace(true) + { + // Solves the empty string problem with multiple std libs + DiagLogMask.reserve(1); + } + + /// @brief . + /// + /// Enables diag logging only on the specified area mask (DNN_RUNTIME=ON | OFF) + std::string DiagLogMask; + + /// @brief . + /// + /// The path to the directory where log files will be written. + /// The path may be relative or absolute. Relative paths are interpreted + /// from the current working directory. + /// Default value is "diaglogs" + std::string LogFileDirectory; + + /// @brief . + /// + //// The name used for log files. If this value is empty then BaseName will be + /// used as the default file name. + /// Default value is "DiagLog" + std::string LogFileName; + + /// @brief . + /// + /// The maximum number of log files to create. If set to 0 no log rotation + /// will be used and the log file name specified will be used each time, overwriting + /// any existing log file that may exist. + /// Default value is 20 + uint32_t LogFileRotateCount; + + /// @brief + /// + /// If the log file already exists, control whether it will be replaced + /// (existing contents truncated), or appended. + /// Default value is true + bool LogFileReplace; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // DiagLog namespace +} // zdl namespace + + +#endif diff --git a/third_party/snpe/include/DlContainer/IDlContainer.hpp b/third_party/snpe/include/DlContainer/IDlContainer.hpp new file mode 100644 index 0000000000..4e29b39bb4 --- /dev/null +++ b/third_party/snpe/include/DlContainer/IDlContainer.hpp @@ -0,0 +1,191 @@ +//============================================================================= +// +// Copyright (c) 2015-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef ZEROTH_IDNC_CONTAINER_HPP +#define ZEROTH_IDNC_CONTAINER_HPP + +#include +#include +#include +#include +#include + +#include "DlSystem/ZdlExportDefine.hpp" +#include "DlSystem/String.hpp" + +namespace zdl { +namespace DlContainer { + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +class IDlContainer; +class dlc_error; + +/** + * The structure of a record in a DL container. + */ +struct ZDL_EXPORT DlcRecord +{ + /// Name of the record. + std::string name; + /// Byte blob holding the data for the record. + std::vector data; + + DlcRecord(); + DlcRecord( DlcRecord&& other ) + : name(std::move(other.name)) + , data(std::move(other.data)) + {} + DlcRecord(const std::string& new_name) + : name(new_name) + , data() + { + if(name.empty()) + { + name.reserve(1); + } + } + DlcRecord(const DlcRecord&) = delete; +}; + +// The maximum length of any record name. +extern const uint32_t RECORD_NAME_MAX_SIZE; +// The maximum size of the record payload (bytes). +extern const uint32_t RECORD_DATA_MAX_SIZE; +// The maximum number of records in an archive at one time. +extern const uint32_t ARCHIVE_MAX_RECORDS; + +/** + * Represents a container for a neural network model which can + * be used to load the model into the SNPE runtime. + */ +class ZDL_EXPORT IDlContainer +{ +public: + /** + * Initializes a container from a container archive file. + * + * @param[in] filename Container archive file path. + * + * @return A pointer to the initialized container + */ + static std::unique_ptr + open(const std::string &filename) noexcept; + + /** + * Initializes a container from a container archive file. + * + * @param[in] filename Container archive file path. + * + * @return A pointer to the initialized container + */ + static std::unique_ptr + open(const zdl::DlSystem::String &filename) noexcept; + + /** + * Initializes a container from a byte buffer. + * + * @param[in] buffer Byte buffer holding the contents of an archive + * file. + * + * @return A pointer to the initialized container + */ + static std::unique_ptr + open(const std::vector &buffer) noexcept; + + /** + * Initializes a container from a byte buffer. + * + * @param[in] buffer Byte buffer holding the contents of an archive + * file. + * + * @param[in] size Size of the byte buffer. + * + * @return A pointer to the initialized container + */ + static std::unique_ptr + open(const uint8_t* buffer, const size_t size) noexcept; + + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + + /** + * Get the record catalog for a container. + * + * @param[out] catalog Buffer that will hold the record names on + * return. + */ + virtual void getCatalog(std::set &catalog) const = 0; + + /** + * Get the record catalog for a container. + * + * @param[out] catalog Buffer that will hold the record names on + * return. + */ + virtual void getCatalog(std::set &catalog) const = 0; + + /** + * Get a record from a container by name. + * + * @param[in] name Name of the record to fetch. + * @param[out] record The passed in record will be populated with the + * record data on return. Note that the caller + * will own the data in the record and is + * responsible for freeing it if needed. + */ + virtual void getRecord(const std::string &name, DlcRecord &record) const = 0; + + /** + * Get a record from a container by name. + * + * @param[in] name Name of the record to fetch. + * @param[out] record The passed in record will be populated with the + * record data on return. Note that the caller + * will own the data in the record and is + * responsible for freeing it if needed. + */ + virtual void getRecord(const zdl::DlSystem::String &name, DlcRecord &record) const = 0; + + /** + * Save the container to an archive on disk. This function will save the + * container if the filename is different from the file that it was opened + * from, or if at least one record was modified since the container was + * opened. + * + * It will truncate any existing file at the target path. + * + * @param filename Container archive file path. + * + * @return indication of success/failure + */ + virtual bool save(const std::string &filename) = 0; + + /** + * Save the container to an archive on disk. This function will save the + * container if the filename is different from the file that it was opened + * from, or if at least one record was modified since the container was + * opened. + * + * It will truncate any existing file at the target path. + * + * @param filename Container archive file path. + * + * @return indication of success/failure + */ + virtual bool save (const zdl::DlSystem::String &filename) = 0; + + virtual ~IDlContainer() {} +}; + +} // ns DlContainer +} // ns zdl + + +#endif diff --git a/third_party/snpe/include/DlSystem/DlEnums.hpp b/third_party/snpe/include/DlSystem/DlEnums.hpp new file mode 100644 index 0000000000..c9b3ef970a --- /dev/null +++ b/third_party/snpe/include/DlSystem/DlEnums.hpp @@ -0,0 +1,234 @@ +//============================================================================== +// +// Copyright (c) 2014-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _DL_ENUMS_HPP_ +#define _DL_ENUMS_HPP_ + +#include "DlSystem/ZdlExportDefine.hpp" + + +namespace zdl { +namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * Enumeration of supported target runtimes. + */ +enum class Runtime_t +{ + /// Run the processing on Snapdragon CPU. + /// Data: float 32bit + /// Math: float 32bit + CPU_FLOAT32 = 0, + + /// Run the processing on the Adreno GPU. + /// Data: float 16bit + /// Math: float 32bit + GPU_FLOAT32_16_HYBRID = 1, + + /// Run the processing on the Hexagon DSP. + /// Data: 8bit fixed point Tensorflow style format + /// Math: 8bit fixed point Tensorflow style format + DSP_FIXED8_TF = 2, + + /// Run the processing on the Adreno GPU. + /// Data: float 16bit + /// Math: float 16bit + GPU_FLOAT16 = 3, + + /// Run the processing on Snapdragon AIX+HVX. + /// Data: 8bit fixed point Tensorflow style format + /// Math: 8bit fixed point Tensorflow style format + AIP_FIXED8_TF = 5, + AIP_FIXED_TF = AIP_FIXED8_TF, + + /// Default legacy enum to retain backward compatibility. + /// CPU = CPU_FLOAT32 + CPU = CPU_FLOAT32, + + /// Default legacy enum to retain backward compatibility. + /// GPU = GPU_FLOAT32_16_HYBRID + GPU = GPU_FLOAT32_16_HYBRID, + + /// Default legacy enum to retain backward compatibility. + /// DSP = DSP_FIXED8_TF + DSP = DSP_FIXED8_TF, + + /// Special value indicating the property is unset. + UNSET = -1 +}; + +/** + * Enumeration of runtime available check options. + */ +enum class RuntimeCheckOption_t +{ + /// Perform standard runtime available check + DEFAULT = 0, + /// Perform standard runtime available check + NORMAL_CHECK = 0, + /// Perform basic runtime available check, may be runtime specific + BASIC_CHECK = 1, + /// Perform unsignedPD runtime available check + UNSIGNEDPD_CHECK = 2, +}; + +/** + * Enumeration of various performance profiles that can be requested. + */ +enum class PerformanceProfile_t +{ + /// Run in a standard mode. + /// This mode will be deprecated in the future and replaced with BALANCED. + DEFAULT = 0, + /// Run in a balanced mode. + BALANCED = 0, + + /// Run in high performance mode + HIGH_PERFORMANCE = 1, + + /// Run in a power sensitive mode, at the expense of performance. + POWER_SAVER = 2, + + /// Use system settings. SNPE makes no calls to any performance related APIs. + SYSTEM_SETTINGS = 3, + + /// Run in sustained high performance mode + SUSTAINED_HIGH_PERFORMANCE = 4, + + /// Run in burst mode + BURST = 5, + + /// Run in lower clock than POWER_SAVER, at the expense of performance. + LOW_POWER_SAVER = 6, + + /// Run in higher clock and provides better performance than POWER_SAVER. + HIGH_POWER_SAVER = 7, + + /// Run in lower balanced mode + LOW_BALANCED = 8, +}; + +/** + * Enumeration of various profilngLevels that can be requested. + */ +enum class ProfilingLevel_t +{ + /// No profiling. + /// Collects no runtime stats in the DiagLog + OFF = 0, + + /// Basic profiling + /// Collects some runtime stats in the DiagLog + BASIC = 1, + + /// Detailed profiling + /// Collects more runtime stats in the DiagLog, including per-layer statistics + /// Performance may be impacted + DETAILED = 2, + + /// Moderate profiling + /// Collects more runtime stats in the DiagLog, no per-layer statistics + MODERATE = 3 +}; + +/** + * Enumeration of various execution priority hints. + */ +enum class ExecutionPriorityHint_t +{ + /// Normal priority + NORMAL = 0, + + /// Higher than normal priority + HIGH = 1, + + /// Lower priority + LOW = 2 + +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++*/ + +/** + * Enumeration that lists the supported image encoding formats. + */ +enum class ImageEncoding_t +{ + /// For unknown image type. Also used as a default value for ImageEncoding_t. + UNKNOWN = 0, + + /// The RGB format consists of 3 bytes per pixel: one byte for + /// Red, one for Green, and one for Blue. The byte ordering is + /// endian independent and is always in RGB byte order. + RGB = 1, + + /// The ARGB32 format consists of 4 bytes per pixel: one byte for + /// Red, one for Green, one for Blue, and one for the alpha channel. + /// The alpha channel is ignored. The byte ordering depends on the + /// underlying CPU. For little endian CPUs, the byte order is BGRA. + /// For big endian CPUs, the byte order is ARGB. + ARGB32 = 2, + + /// The RGBA format consists of 4 bytes per pixel: one byte for + /// Red, one for Green, one for Blue, and one for the alpha channel. + /// The alpha channel is ignored. The byte ordering is endian independent + /// and is always in RGBA byte order. + RGBA = 3, + + /// The GRAYSCALE format is for 8-bit grayscale. + GRAYSCALE = 4, + + /// NV21 is the Android version of YUV. The Chrominance is down + /// sampled and has a subsampling ratio of 4:2:0. Note that this + /// image format has 3 channels, but the U and V channels + /// are subsampled. For every four Y pixels there is one U and one V pixel. @newpage + NV21 = 5, + + /// The BGR format consists of 3 bytes per pixel: one byte for + /// Red, one for Green and one for Blue. The byte ordering is + /// endian independent and is always BGR byte order. + BGR = 6 +}; + +/** + * Enumeration that lists the supported LogLevels that can be set by users. + */ +enum class LogLevel_t +{ + /// Enumeration variable to be used by user to set logging level to FATAL. + LOG_FATAL = 0, + + /// Enumeration variable to be used by user to set logging level to ERROR. + LOG_ERROR = 1, + + /// Enumeration variable to be used by user to set logging level to WARN. + LOG_WARN = 2, + + /// Enumeration variable to be used by user to set logging level to INFO. + LOG_INFO = 3, + + /// Enumeration variable to be used by user to set logging level to VERBOSE. + LOG_VERBOSE = 4 +}; + +typedef enum : int +{ + UNSPECIFIED = 0, + FLOATING_POINT_32 = 1, + FLOATING_POINT_16 = 2, + FIXED_POINT_8 = 3, + FIXED_POINT_16 = 4 +} IOBufferDataType_t; + +}} // namespaces end + + +#endif diff --git a/third_party/snpe/include/DlSystem/DlError.hpp b/third_party/snpe/include/DlSystem/DlError.hpp new file mode 100644 index 0000000000..57592f01ba --- /dev/null +++ b/third_party/snpe/include/DlSystem/DlError.hpp @@ -0,0 +1,259 @@ +//============================================================================== +// +// Copyright (c) 2016-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _DL_ERROR_HPP_ +#define _DL_ERROR_HPP_ + +#include +#include // numeric_limits + +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl { +namespace DlSystem { + +// clang and arm gcc different in how ZDL_EXPORT is used with enum class +#if !defined (__clang__) +enum class ErrorCode : uint32_t ZDL_EXPORT { +#else +enum class ZDL_EXPORT ErrorCode : uint32_t { +#endif // ARM64V8A + NONE = 0, + + // System config errors + SNPE_CONFIG_MISSING_PARAM = 100, + SNPE_CONFIG_INVALID_PARAM = 101, + SNPE_CONFIG_MISSING_FILE = 102, + SNPE_CONFIG_NNCONFIG_NOT_SET = 103, + SNPE_CONFIG_NNCONFIG_INVALID = 104, + SNPE_CONFIG_WRONG_INPUT_NAME = 105, + SNPE_CONFIG_INCORRECT_INPUT_DIMENSIONS = 106, + SNPE_CONFIG_DIMENSIONS_MODIFICATION_NOT_SUPPORTED = 107, + SNPE_CONFIG_BOTH_OUTPUT_LAYER_TENSOR_NAMES_SET = 108, + + SNPE_CONFIG_NNCONFIG_ONLY_TENSOR_SUPPORTED = 120, + SNPE_CONFIG_NNCONFIG_ONLY_USER_BUFFER_SUPPORTED = 121, + + // DlSystem errors + SNPE_DLSYSTEM_MISSING_BUFFER = 200, + SNPE_DLSYSTEM_TENSOR_CAST_FAILED = 201, + SNPE_DLSYSTEM_FIXED_POINT_PARAM_INVALID = 202, + SNPE_DLSYSTEM_SIZE_MISMATCH = 203, + SNPE_DLSYSTEM_NAME_NOT_FOUND = 204, + SNPE_DLSYSTEM_VALUE_MISMATCH = 205, + SNPE_DLSYSTEM_INSERT_FAILED = 206, + SNPE_DLSYSTEM_TENSOR_FILE_READ_FAILED = 207, + SNPE_DLSYSTEM_DIAGLOG_FAILURE = 208, + SNPE_DLSYSTEM_LAYER_NOT_SET = 209, + SNPE_DLSYSTEM_WRONG_NUMBER_INPUT_BUFFERS = 210, + SNPE_DLSYSTEM_RUNTIME_TENSOR_SHAPE_MISMATCH = 211, + SNPE_DLSYSTEM_TENSOR_MISSING = 212, + SNPE_DLSYSTEM_TENSOR_ITERATION_UNSUPPORTED = 213, + SNPE_DLSYSTEM_BUFFER_MANAGER_MISSING = 214, + SNPE_DLSYSTEM_RUNTIME_BUFFER_SOURCE_UNSUPPORTED = 215, + SNPE_DLSYSTEM_BUFFER_CAST_FAILED = 216, + SNPE_DLSYSTEM_WRONG_TRANSITION_TYPE = 217, + SNPE_DLSYSTEM_LAYER_ALREADY_REGISTERED = 218, + SNPE_DLSYSTEM_TENSOR_DIM_INVALID = 219, + + SNPE_DLSYSTEM_BUFFERENCODING_UNKNOWN = 240, + SNPE_DLSYSTEM_BUFFER_INVALID_PARAM = 241, + + // DlContainer errors + SNPE_DLCONTAINER_MODEL_PARSING_FAILED = 300, + SNPE_DLCONTAINER_UNKNOWN_LAYER_CODE = 301, + SNPE_DLCONTAINER_MISSING_LAYER_PARAM = 302, + SNPE_DLCONTAINER_LAYER_PARAM_NOT_SUPPORTED = 303, + SNPE_DLCONTAINER_LAYER_PARAM_INVALID = 304, + SNPE_DLCONTAINER_TENSOR_DATA_MISSING = 305, + SNPE_DLCONTAINER_MODEL_LOAD_FAILED = 306, + SNPE_DLCONTAINER_MISSING_RECORDS = 307, + SNPE_DLCONTAINER_INVALID_RECORD = 308, + SNPE_DLCONTAINER_WRITE_FAILURE = 309, + SNPE_DLCONTAINER_READ_FAILURE = 310, + SNPE_DLCONTAINER_BAD_CONTAINER = 311, + SNPE_DLCONTAINER_BAD_DNN_FORMAT_VERSION = 312, + SNPE_DLCONTAINER_UNKNOWN_AXIS_ANNOTATION = 313, + SNPE_DLCONTAINER_UNKNOWN_SHUFFLE_TYPE = 314, + SNPE_DLCONTAINER_TEMP_FILE_FAILURE = 315, + + // Network errors + SNPE_NETWORK_EMPTY_NETWORK = 400, + SNPE_NETWORK_CREATION_FAILED = 401, + SNPE_NETWORK_PARTITION_FAILED = 402, + SNPE_NETWORK_NO_OUTPUT_DEFINED = 403, + SNPE_NETWORK_MISMATCH_BETWEEN_NAMES_AND_DIMS = 404, + SNPE_NETWORK_MISSING_INPUT_NAMES = 405, + SNPE_NETWORK_MISSING_OUTPUT_NAMES = 406, + SNPE_NETWORK_EXECUTION_FAILED = 407, + + // Host runtime errors + SNPE_HOST_RUNTIME_TARGET_UNAVAILABLE = 500, + + // CPU runtime errors + SNPE_CPU_LAYER_NOT_SUPPORTED = 600, + SNPE_CPU_LAYER_PARAM_NOT_SUPPORTED = 601, + SNPE_CPU_LAYER_PARAM_INVALID = 602, + SNPE_CPU_LAYER_PARAM_COMBINATION_INVALID = 603, + SNPE_CPU_BUFFER_NOT_FOUND = 604, + SNPE_CPU_NETWORK_NOT_SUPPORTED = 605, + SNPE_CPU_UDO_OPERATION_FAILED = 606, + + // CPU fixed-point runtime errors + SNPE_CPU_FXP_LAYER_NOT_SUPPORTED = 700, + SNPE_CPU_FXP_LAYER_PARAM_NOT_SUPPORTED = 701, + SNPE_CPU_FXP_LAYER_PARAM_INVALID = 702, + + // GPU runtime errors + SNPE_GPU_LAYER_NOT_SUPPORTED = 800, + SNPE_GPU_LAYER_PARAM_NOT_SUPPORTED = 801, + SNPE_GPU_LAYER_PARAM_INVALID = 802, + SNPE_GPU_LAYER_PARAM_COMBINATION_INVALID = 803, + SNPE_GPU_KERNEL_COMPILATION_FAILED = 804, + SNPE_GPU_CONTEXT_NOT_SET = 805, + SNPE_GPU_KERNEL_NOT_SET = 806, + SNPE_GPU_KERNEL_PARAM_INVALID = 807, + SNPE_GPU_OPENCL_CHECK_FAILED = 808, + SNPE_GPU_OPENCL_FUNCTION_ERROR = 809, + SNPE_GPU_BUFFER_NOT_FOUND = 810, + SNPE_GPU_TENSOR_DIM_INVALID = 811, + SNPE_GPU_MEMORY_FLAGS_INVALID = 812, + SNPE_GPU_UNEXPECTED_NUMBER_OF_IO = 813, + SNPE_GPU_LAYER_PROXY_ERROR = 814, + SNPE_GPU_BUFFER_IN_USE = 815, + SNPE_GPU_BUFFER_MODIFICATION_ERROR = 816, + SNPE_GPU_DATA_ARRANGEMENT_INVALID = 817, + SNPE_GPU_UDO_OPERATION_FAILED = 818, + // DSP runtime errors + SNPE_DSP_LAYER_NOT_SUPPORTED = 900, + SNPE_DSP_LAYER_PARAM_NOT_SUPPORTED = 901, + SNPE_DSP_LAYER_PARAM_INVALID = 902, + SNPE_DSP_LAYER_PARAM_COMBINATION_INVALID = 903, + SNPE_DSP_STUB_NOT_PRESENT = 904, + SNPE_DSP_LAYER_NAME_TRUNCATED = 905, + SNPE_DSP_LAYER_INPUT_BUFFER_NAME_TRUNCATED = 906, + SNPE_DSP_LAYER_OUTPUT_BUFFER_NAME_TRUNCATED = 907, + SNPE_DSP_RUNTIME_COMMUNICATION_ERROR = 908, + SNPE_DSP_RUNTIME_INVALID_PARAM_ERROR = 909, + SNPE_DSP_RUNTIME_SYSTEM_ERROR = 910, + SNPE_DSP_RUNTIME_CRASHED_ERROR = 911, + SNPE_DSP_BUFFER_SIZE_ERROR = 912, + SNPE_DSP_UDO_EXECUTE_ERROR = 913, + SNPE_DSP_UDO_LIB_NOT_REGISTERED_ERROR = 914, + SNPE_DSP_UDO_INVALID_QUANTIZATION_TYPE_ERROR = 915, + SNPE_DSP_RUNTIME_INVALID_RPC_DRIVER = 916, + SNPE_DSP_RUNTIME_RPC_PERMISSION_ERROR = 917, + SNPE_DSP_RUNTIME_DSP_FILE_OPEN_ERROR = 918, + + // Model validataion errors + SNPE_MODEL_VALIDATION_LAYER_NOT_SUPPORTED = 1000, + SNPE_MODEL_VALIDATION_LAYER_PARAM_NOT_SUPPORTED = 1001, + SNPE_MODEL_VALIDATION_LAYER_PARAM_INVALID = 1002, + SNPE_MODEL_VALIDATION_LAYER_PARAM_MISSING = 1003, + SNPE_MODEL_VALIDATION_LAYER_PARAM_COMBINATION_INVALID = 1004, + SNPE_MODEL_VALIDATION_LAYER_ORDERING_INVALID = 1005, + SNPE_MODEL_VALIDATION_INVALID_CONSTRAINT = 1006, + SNPE_MODEL_VALIDATION_MISSING_BUFFER = 1007, + SNPE_MODEL_VALIDATION_BUFFER_REUSE_NOT_SUPPORTED = 1008, + SNPE_MODEL_VALIDATION_LAYER_COULD_NOT_BE_ASSIGNED = 1009, + SNPE_MODEL_VALIDATION_UDO_LAYER_FAILED = 1010, + + // UDL errors + SNPE_UDL_LAYER_EMPTY_UDL_NETWORK = 1100, + SNPE_UDL_LAYER_PARAM_INVALID = 1101, + SNPE_UDL_LAYER_INSTANCE_MISSING = 1102, + SNPE_UDL_LAYER_SETUP_FAILED = 1103, + SNPE_UDL_EXECUTE_FAILED = 1104, + SNPE_UDL_BUNDLE_INVALID = 1105, + SNPE_UDO_REGISTRATION_FAILED = 1106, + SNPE_UDO_GET_PACKAGE_FAILED = 1107, + SNPE_UDO_GET_IMPLEMENTATION_FAILED = 1108, + + // Dependent library errors + SNPE_STD_LIBRARY_ERROR = 1200, + + // Unknown exception (catch (...)), Has no component attached to this + SNPE_UNKNOWN_EXCEPTION = 1210, + + // Storage Errors + SNPE_STORAGE_INVALID_KERNEL_REPO = 1300, + + // AIP runtime errors + SNPE_AIP_LAYER_NOT_SUPPORTED = 1400, + SNPE_AIP_LAYER_PARAM_NOT_SUPPORTED = 1401, + SNPE_AIP_LAYER_PARAM_INVALID = 1402, + SNPE_AIP_LAYER_PARAM_COMBINATION_INVALID = 1403, + SNPE_AIP_STUB_NOT_PRESENT = 1404, + SNPE_AIP_LAYER_NAME_TRUNCATED = 1405, + SNPE_AIP_LAYER_INPUT_BUFFER_NAME_TRUNCATED = 1406, + SNPE_AIP_LAYER_OUTPUT_BUFFER_NAME_TRUNCATED = 1407, + SNPE_AIP_RUNTIME_COMMUNICATION_ERROR = 1408, + SNPE_AIP_RUNTIME_INVALID_PARAM_ERROR = 1409, + SNPE_AIP_RUNTIME_SYSTEM_ERROR = 1410, + SNPE_AIP_RUNTIME_TENSOR_MISSING = 1411, + SNPE_AIP_RUNTIME_TENSOR_SHAPE_MISMATCH = 1412, + SNPE_AIP_RUNTIME_BAD_AIX_RECORD = 1413, + + // DlCaching errors + SNPE_DLCACHING_INVALID_METADATA = 1500, + SNPE_DLCACHING_INVALID_INITBLOB = 1501, + + // Infrastructure Errors + SNPE_INFRA_CLUSTERMGR_INSTANCE_INVALID = 1600, + SNPE_INFRA_CLUSTERMGR_EXECUTE_SYNC_FAILED = 1601, + + // Memory Errors + SNPE_MEMORY_CORRUPTION_ERROR = 1700 + +}; + + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * Returns the error code of the last error encountered. + * + * @return The error code. + * + * @note The returned error code is significant only when the return + * value of the call indicated an error. + */ +ZDL_EXPORT ErrorCode getLastErrorCode(); + +/** + * Returns the error string of the last error encountered. + * + * @return The error string. + * + * @note The returned error string is significant only when the return + * value of the call indicated an error. + */ +ZDL_EXPORT const char* getLastErrorString(); + +/** + * Returns the info string of the last error encountered. + */ +ZDL_EXPORT const char* getLastInfoString(); + +/** + * Returns the uint32_t representation of the error code enum. + * + * @param[in] code The error code to be converted. + * + * @return uint32_t representation of the error code. + */ +ZDL_EXPORT uint32_t enumToUInt32(zdl::DlSystem::ErrorCode code); + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // DlSystem +} // zdl + +#endif // _DL_ERROR_HPP_ + diff --git a/third_party/snpe/include/DlSystem/DlOptional.hpp b/third_party/snpe/include/DlSystem/DlOptional.hpp new file mode 100644 index 0000000000..4f83e6b4e4 --- /dev/null +++ b/third_party/snpe/include/DlSystem/DlOptional.hpp @@ -0,0 +1,225 @@ +//============================================================================== +// +// Copyright (c) 2016, 2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _DL_SYSTEM_OPTIONAL_HPP_ +#define _DL_SYSTEM_OPTIONAL_HPP_ + +#include +#include +#include + +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl { +namespace DlSystem { + +template + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * Class to manage a value that may or may not exist. The boolean value + * of the Optional class is true if the object contains a value and false + * if it does not contain a value. + * + * The class must be evaluated and confirmed as true (containing a value) + * before being dereferenced. + */ +class ZDL_EXPORT Optional final { +public: + enum class LIFECYCLE { + NONE = 0, + REFERENCE_OWNED = 1, + POINTER_OWNED = 2, + POINTER_NOT_OWNED = 3 + }; + + struct ReferenceCount { + size_t count = 0; + + void increment() { count++; } + + size_t decrement() { + if (count > 0) { + count--; + } + return count; + } + }; + + using U = typename std::remove_pointer::type; + + /** + * The default constructor is set to not have any value, and is + * therefore evaluated as false. + */ + // Do not explicit it so we can return {} + Optional() { + m_Type = LIFECYCLE::NONE; + } + + /** + * Construct an Optional class using an object. + * @param[in] Reference to an object v + * @param[out] Optional instance of object v + */ + template + Optional (const T& v, typename std::enable_if::value>::type* = 0) + : m_Type(LIFECYCLE::REFERENCE_OWNED) { + try { + m_StoragePtr = new T(v); + } catch (...) { + m_StoragePtr = nullptr; + m_Type = LIFECYCLE::NONE; + } + } + + template + Optional(U* v, LIFECYCLE type, typename std::enable_if::value>::type* = 0) + : m_Type(type) { + switch (m_Type) { + case LIFECYCLE::POINTER_OWNED: + m_StoragePtr = v; + m_Count = new ReferenceCount(); + m_Count->increment(); + break; + case LIFECYCLE::POINTER_NOT_OWNED: + m_StoragePtr = v; + break; + case LIFECYCLE::REFERENCE_OWNED: + throw std::bad_exception(); + case LIFECYCLE::NONE: + break; + } + } + + Optional(const Optional &other) : m_Type(other.m_Type), m_Count(other.m_Count) { + if (isReference()) { + m_StoragePtr = new U(*other.m_StoragePtr); + } else if (isPointer()) { + m_StoragePtr = other.m_StoragePtr; + if (isOwned()) { + m_Count->increment(); + } + } + } + + Optional& operator=(const Optional& other) noexcept { + Optional tmp(other); + swap(std::move(tmp)); + return *this; + } + + Optional(Optional&& other) noexcept { + swap(std::move(other)); + } + + Optional& operator=(Optional&& other) noexcept { + swap(std::move(other)); + return *this; + } + + ~Optional() { + if (isOwned()) { + if (isReference() || (isPointer() && m_Count->decrement() == 0)) { + delete m_StoragePtr; + delete m_Count; + } + } + } + + /** + * Boolean value of Optional class is only true when there exists a value. + */ + operator bool() const noexcept { return isValid(); } + + bool operator!() const noexcept { return !isValid(); } + + /** + * Get reference of Optional object + * @warning User must validate Optional has value before. + */ + const T& operator*() { return this->GetReference(); } + + /** + * Get reference of Optional object + * @warning User must validate Optional has value before. + */ + const T& operator*() const { return this->GetReference(); } + + operator T&() { return this->GetReference(); } + + T operator->() { + T self = this->GetReference(); + return self; + } +private: + void swap(Optional&& other) { + m_Type = other.m_Type; + m_StoragePtr = other.m_StoragePtr; + m_Count = other.m_Count; + + other.m_Type = LIFECYCLE::NONE; + other.m_StoragePtr = nullptr; + other.m_Count = nullptr; + } + + template + typename std::enable_if::value, const Q&>::type GetReference() const noexcept { + if (!isReference()) std::terminate(); + return *static_cast(m_StoragePtr); + } + + template + typename std::enable_if::value, const Q&>::type GetReference() const noexcept { + if (!isPointer()) std::terminate(); + return static_cast(m_StoragePtr); + } + + template + typename std::enable_if::value, Q&>::type GetReference() noexcept { + if (!isReference()) std::terminate(); + return *m_StoragePtr; + } + + template + typename std::enable_if::value, Q&>::type GetReference() noexcept { + if (!isPointer()) std::terminate(); + return m_StoragePtr; + } + + bool isPointer() const { + return m_Type == LIFECYCLE::POINTER_OWNED || m_Type == LIFECYCLE::POINTER_NOT_OWNED; + } + + bool isOwned() const { + return m_Type == LIFECYCLE::REFERENCE_OWNED || m_Type == LIFECYCLE::POINTER_OWNED; + } + + bool isReference() const { + return m_Type == LIFECYCLE::REFERENCE_OWNED; + } + + bool isValid() const { + return m_Type != LIFECYCLE::NONE; + } + + U* m_StoragePtr = nullptr; + LIFECYCLE m_Type; + ReferenceCount *m_Count = nullptr; +}; + +} // ns DlSystem +} // ns zdl + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // _DL_SYSTEM_OPTIONAL_HPP_ diff --git a/third_party/snpe/include/DlSystem/DlVersion.hpp b/third_party/snpe/include/DlSystem/DlVersion.hpp new file mode 100644 index 0000000000..beb8d75f21 --- /dev/null +++ b/third_party/snpe/include/DlSystem/DlVersion.hpp @@ -0,0 +1,78 @@ +//============================================================================== +// +// Copyright (c) 2014-2015 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + + +#ifndef _DL_VERSION_HPP_ +#define _DL_VERSION_HPP_ + +#include "ZdlExportDefine.hpp" +#include +#include +#include "DlSystem/String.hpp" + + +namespace zdl { +namespace DlSystem +{ + class Version_t; +}} + + +namespace zdl { namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * A class that contains the different portions of a version number. + */ +class ZDL_EXPORT Version_t +{ +public: + /// Holds the major version number. Changes in this value indicate + /// major changes that break backward compatibility. + int32_t Major; + + /// Holds the minor version number. Changes in this value indicate + /// minor changes made to library that are backwards compatible + /// (such as additions to the interface). + int32_t Minor; + + /// Holds the teeny version number. Changes in this value indicate + /// changes such as bug fixes and patches made to the library that + /// do not affect the interface. + int32_t Teeny; + + /// This string holds information about the build version. + /// + std::string Build; + + static zdl::DlSystem::Version_t fromString(const std::string &stringValue); + + static zdl::DlSystem::Version_t fromString(const zdl::DlSystem::String &stringValue); + + /** + * @brief Returns a string in the form Major.Minor.Teeny.Build + * + * @return A formatted string holding the version information. + */ + const std::string toString() const; + + /** + * @brief Returns a string in the form Major.Minor.Teeny.Build + * + * @return A formatted string holding the version information. + */ + const zdl::DlSystem::String asString() const; +}; + +}} + +/** @} */ /* end_addtogroup c_plus_plus_apis */ + +#endif diff --git a/third_party/snpe/include/DlSystem/IBufferAttributes.hpp b/third_party/snpe/include/DlSystem/IBufferAttributes.hpp new file mode 100644 index 0000000000..f893e0a237 --- /dev/null +++ b/third_party/snpe/include/DlSystem/IBufferAttributes.hpp @@ -0,0 +1,86 @@ +//============================================================================== +// +// Copyright (c) 2017-2019 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _IBUFFER_ATTRIBUTES_HPP +#define _IBUFFER_ATTRIBUTES_HPP +#include "IUserBuffer.hpp" +#include "TensorShape.hpp" +#include "ZdlExportDefine.hpp" + +namespace zdl { + namespace DlSystem { + class UserBufferEncoding; + } +} + +namespace zdl { +namespace DlSystem { + +/** + * @brief IBufferAttributes returns a buffer's dimension and alignment + * requirements, along with info on its encoding type + */ +class ZDL_EXPORT IBufferAttributes { +public: + + /** + * @brief Gets the buffer's element size, in bytes + * + * This can be used to compute the memory size required + * to back this buffer. + * + * @return Element size, in bytes + */ + virtual size_t getElementSize() const noexcept = 0; + + /** + * @brief Gets the element's encoding type + * + * @return encoding type + */ + virtual zdl::DlSystem::UserBufferEncoding::ElementType_t getEncodingType() const noexcept = 0; + + /** + * @brief Gets the number of elements in each dimension + * + * @return Dimension size, in terms of number of elements + */ + virtual const TensorShape getDims() const noexcept = 0; + + /** + * @brief Gets the alignment requirement of each dimension + * + * Alignment per each dimension is expressed as an multiple, for + * example, if one particular dimension can accept multiples of 8, + * the alignment will be 8. + * + * @return Alignment in each dimension, in terms of multiple of + * number of elements + */ + virtual const TensorShape getAlignments() const noexcept = 0; + + /** + * @brief Gets the buffer encoding returned from the network responsible + * for generating this buffer. Depending on the encoding type, this will + * be an instance of an encoding type specific derived class. + * + * @return Derived user buffer encoding object. + */ + virtual zdl::DlSystem::UserBufferEncoding* getEncoding() const noexcept = 0; + + virtual ~IBufferAttributes() {} +}; + + + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} +} + +#endif diff --git a/third_party/snpe/include/DlSystem/IOBufferDataTypeMap.hpp b/third_party/snpe/include/DlSystem/IOBufferDataTypeMap.hpp new file mode 100644 index 0000000000..ac33c84af8 --- /dev/null +++ b/third_party/snpe/include/DlSystem/IOBufferDataTypeMap.hpp @@ -0,0 +1,127 @@ +//============================================================================= +// +// Copyright (c) 2021-2022 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + + +#ifndef DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP +#define DL_SYSTEM_IOBUFFER_DATATYPE_MAP_HPP + +#include +#include +#include "DlSystem/DlEnums.hpp" + +namespace DlSystem +{ + // Forward declaration of IOBufferDataTypeMapImpl implementation. + class IOBufferDataTypeMapImpl; +} + +namespace zdl +{ +namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * The IoBufferDataTypeMap class definition + */ +class ZDL_EXPORT IOBufferDataTypeMap final +{ +public: + + /** + * @brief . + * + * Creates a new Buffer Data type map + * + */ + IOBufferDataTypeMap(); + + /** + * @brief Adds a name and the corresponding buffer data type + * to the map + * + * @param[name] name The name of the buffer + * @param[bufferDataType] buffer Data Type of the buffer + * + * @note If a buffer with the same name already exists, no new + * buffer is added. + */ + void add(const char* name, zdl::DlSystem::IOBufferDataType_t bufferDataType); + + /** + * @brief Removes a buffer name from the map + * + * @param[name] name The name of the buffer + * + */ + void remove(const char* name); + + /** + * @brief Returns the type of the named buffer + * + * @param[name] name The name of the buffer + * + * @return The type of the buffer, or UNSPECIFIED if the buffer does not exist + * + */ + zdl::DlSystem::IOBufferDataType_t getBufferDataType(const char* name); + + /** + * @brief Returns the type of the first buffer + * + * @return The type of the first buffer, or UNSPECIFIED if the map is empty. + * + */ + zdl::DlSystem::IOBufferDataType_t getBufferDataType(); + + /** + * @brief Returns the size of the buffer type map. + * + * @return The size of the map + * + */ + size_t size(); + + /** + * @brief Checks the existence of the named buffer in the map + * + * @return True if the named buffer exists, false otherwise. + * + */ + bool find(const char* name); + + /** + * @brief Resets the map + * + */ + void clear(); + + /** + * @brief Checks whether the map is empty + * + * @return True if the map is empty, false otherwise. + * + */ + bool empty(); + + /** + * @brief Destroys the map + * + */ + ~IOBufferDataTypeMap(); + +private: + std::shared_ptr<::DlSystem::IOBufferDataTypeMapImpl> m_IOBufferDataTypeMapImpl; +}; +} + +} +#endif diff --git a/third_party/snpe/include/DlSystem/ITensor.hpp b/third_party/snpe/include/DlSystem/ITensor.hpp new file mode 100644 index 0000000000..2f006c857f --- /dev/null +++ b/third_party/snpe/include/DlSystem/ITensor.hpp @@ -0,0 +1,146 @@ +//============================================================================= +// +// Copyright (c) 2015-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _ITENSOR_HPP_ +#define _ITENSOR_HPP_ + +#include "ITensorItr.hpp" +#include "ITensorItrImpl.hpp" +#include "TensorShape.hpp" +#include "ZdlExportDefine.hpp" +#include +#include +#include + +namespace zdl { +namespace DlSystem +{ + class ITensor; +}} + +namespace zdl { namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * Represents a tensor which holds n-dimensional data. It is important to + * understand how the tensor data is represented in memory + * relative to the tensor dimensions. Tensors store data in + * memory in row-major order (i.e. the last tensor dimension is + * the fastest varying one). For example, if you have a two + * dimensional tensor with 3 rows and 2 columns (i.e. the tensor + * dimensions are 3,2 as returned in tensor dimension vectors) + * with the following data in terms rows and columns: + * + * | 1 2 |
+ * | 3 4 |
+ * | 5 6 |
+ * + * This data would be stored in memory as 1,2,3,4,5,6. + */ +class ZDL_EXPORT ITensor +{ +public: + + typedef zdl::DlSystem::ITensorItr iterator; + typedef zdl::DlSystem::ITensorItr const_iterator; + + virtual ~ITensor() {} + + /** + * Returns a tensor iterator pointing to the beginning + * of the data in the tensor. + * + * @return A tensor iterator that points to the first data + * element in the tensor. + */ + virtual iterator begin() = 0; + + /** + * Returns the const version of a tensor iterator + * pointing to the beginning of the data in the tensor. + * + * @return A tensor const iterator that points to the first data + * element in the tensor. + */ + virtual const_iterator cbegin() const = 0; + + /** + * Returns a tensor iterator pointing to the end of the + * data in the tensor. This tensor should not be + * dereferenced. + * + * @return A tensor iterator that points to the end of the data + * (one past the last element) in the tensor. + */ + virtual iterator end() = 0; + + /** + * Returns the const version of a tensor iterator + * pointing to the end of the data in the tensor. This + * tensor should not be dereferenced. + * + * @return A tensor const iterator that points to the end of the + * data (one past the last element) in the tensor. + */ + virtual const_iterator cend() const = 0; + + /** + * @brief Gets the shape of this tensor. + * + * The last element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying dimension, etc. + * + * @return A shape class holding the tensor dimensions. + */ + virtual TensorShape getShape() const = 0; + + /** + * Returns the element size of the data in the tensor + * (discounting strides). This is how big a buffer would + * need to be to hold the tensor data contiguously in + * memory. + * + * @return The size of the tensor (in elements). + */ + virtual size_t getSize() const = 0; + + /** + * @brief Serializes the tensor to an output stream. + * + * @param[in] output The output stream to which to write the tensor + * + * @throw std::runtime_error If the stream is ever in a bad + * state before the tensor is fully serialized. + */ + virtual void serialize(std::ostream &output) const = 0; + + friend iterator; + friend const_iterator; + + virtual bool isQuantized() {return false;} + virtual float GetDelta() {return NAN;}; + virtual float GetOffset() {return NAN;}; + +protected: + + /** + * Returns the tensor iterator implementation. + * + * @return A pointer to the tensor iterator implementation. + */ + virtual std::unique_ptr<::DlSystem::ITensorItrImpl> getItrImpl() const = 0; +}; + +}} + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif diff --git a/third_party/snpe/include/DlSystem/ITensorFactory.hpp b/third_party/snpe/include/DlSystem/ITensorFactory.hpp new file mode 100644 index 0000000000..57d2c8ea99 --- /dev/null +++ b/third_party/snpe/include/DlSystem/ITensorFactory.hpp @@ -0,0 +1,92 @@ +//============================================================================= +// +// Copyright (c) 2015-2016 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _ITENSOR_FACTORY_HPP +#define _ITENSOR_FACTORY_HPP + +#include "ITensor.hpp" +#include "TensorShape.hpp" +#include "ZdlExportDefine.hpp" +#include + +namespace zdl { + namespace DlSystem + { + class ITensor; + class TensorShape; + } +} + +namespace zdl { namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * Factory interface class to create ITensor objects. + */ +class ZDL_EXPORT ITensorFactory +{ +public: + virtual ~ITensorFactory() = default; + + /** + * Creates a new ITensor with uninitialized data. + * + * The strides for the tensor will match the tensor dimensions + * (i.e., the tensor data is contiguous in memory). + * + * @param[in] shape The dimensions for the tensor in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + * @return A pointer to the created tensor or nullptr if creating failed. + */ + virtual std::unique_ptr + createTensor(const TensorShape &shape) noexcept = 0; + + /** + * Creates a new ITensor by loading it from a file. + * + * @param[in] input The input stream from which to read the tensor + * data. + * + * @return A pointer to the created tensor or nullptr if creating failed. + * + */ + virtual std::unique_ptr createTensor(std::istream &input) noexcept = 0; + + /** + * Create a new ITensor with specific data. + * (i.e. the tensor data is contiguous in memory). This tensor is + * primarily used to create a tensor where tensor size can't be + * computed directly from dimension. One such example is + * NV21-formatted image, or any YUV formatted image + * + * @param[in] shape The dimensions for the tensor in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + * @param[in] data The actual data with which the Tensor object is filled. + * + * @param[in] dataSize The size of data + * + * @return A pointer to the created tensor + */ + virtual std::unique_ptr + createTensor(const TensorShape &shape, const unsigned char *data, size_t dataSize) noexcept = 0; +}; + +}} + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif diff --git a/third_party/snpe/include/DlSystem/ITensorItr.hpp b/third_party/snpe/include/DlSystem/ITensorItr.hpp new file mode 100644 index 0000000000..4ce12a9f11 --- /dev/null +++ b/third_party/snpe/include/DlSystem/ITensorItr.hpp @@ -0,0 +1,182 @@ +//============================================================================= +// +// Copyright (c) 2015 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _ITENSOR_ITR_HPP_ +#define _ITENSOR_ITR_HPP_ + +#include "ZdlExportDefine.hpp" +#include "ITensorItrImpl.hpp" + +#include +#include +#include + +namespace zdl { +namespace DlSystem +{ + template class ITensorItr; + class ITensor; + void ZDL_EXPORT fill(ITensorItr first, ITensorItr end, float val); + template OutItr ZDL_EXPORT copy(InItr first, InItr last, OutItr result) + { + return std::copy(first, last, result); + } +}} +namespace DlSystem +{ + class ITensorItrImpl; +} + +namespace zdl { namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * A bidirectional iterator (with limited random access + * capabilities) for the zdl::DlSystem::ITensor class. + * + * This is a standard bidrectional iterator and is compatible + * with standard algorithm functions that operate on bidirectional + * access iterators (e.g., std::copy, std::fill, etc.). It uses a + * template parameter to create const and non-const iterators + * from the same code. Iterators are easiest to declare via the + * typedefs iterator and const_iterator in the ITensor class + * (e.g., zdl::DlSystem::ITensor::iterator). + * + * Note that if the tensor the iterator is traversing was + * created with nondefault (i.e., nontrivial) strides, the + * iterator will obey the strides when traversing the tensor + * data. + * + * Also note that nontrivial strides dramatically affect the + * performance of the iterator (on the order of 20x slower). + */ +template +class ZDL_EXPORT ITensorItr : public std::iterator +{ +public: + + typedef typename std::conditional::type VALUE_REF; + + ITensorItr() = delete; + virtual ~ITensorItr() {} + + ITensorItr(std::unique_ptr<::DlSystem::ITensorItrImpl> impl, + bool isTrivial = false, + float* data = nullptr) + : m_Impl(impl->clone()) + , m_IsTrivial(isTrivial) + , m_Data(data) + , m_DataStart(data) {} + + ITensorItr(const ITensorItr& itr) + : m_Impl(itr.m_Impl->clone()), + m_IsTrivial(itr.m_IsTrivial), + m_Data(itr.m_Data), + m_DataStart(itr.m_DataStart) {} + + zdl::DlSystem::ITensorItr& operator=(const ITensorItr& other) + { + if (this == &other) return *this; + m_Impl = std::move(other.m_Impl->clone()); + m_IsTrivial = other.m_IsTrivial; + m_Data = other.m_Data; + m_DataStart = other.m_DataStart; + return *this; + } + + inline zdl::DlSystem::ITensorItr& operator++() + { + if (m_IsTrivial) m_Data++; else m_Impl->increment(); + return *this; + } + inline zdl::DlSystem::ITensorItr operator++(int) + { + ITensorItr tmp(*this); + operator++(); + return tmp; + } + inline zdl::DlSystem::ITensorItr& operator--() + { + if (m_IsTrivial) m_Data--; else m_Impl->decrement(); + return *this; + } + inline zdl::DlSystem::ITensorItr operator--(int) + { + ITensorItr tmp(*this); + operator--(); + return tmp; + } + inline zdl::DlSystem::ITensorItr& operator+=(int rhs) + { + if (m_IsTrivial) m_Data += rhs; else m_Impl->increment(rhs); + return *this; + } + inline friend zdl::DlSystem::ITensorItr operator+(zdl::DlSystem::ITensorItr lhs, int rhs) + { lhs += rhs; return lhs; } + inline zdl::DlSystem::ITensorItr& operator-=(int rhs) + { + if (m_IsTrivial) m_Data -= rhs; else m_Impl->decrement(rhs); + return *this; + } + inline friend zdl::DlSystem::ITensorItr operator-(zdl::DlSystem::ITensorItr lhs, int rhs) + { lhs -= rhs; return lhs; } + + inline size_t operator-(const zdl::DlSystem::ITensorItr& rhs) + { + if (m_IsTrivial) return (m_Data - m_DataStart) - (rhs.m_Data - rhs.m_DataStart); + return m_Impl->getPosition() - rhs.m_Impl->getPosition(); + } + + inline friend bool operator<(const ITensorItr& lhs, const ITensorItr& rhs) + { + if (lhs.m_IsTrivial) return lhs.m_Data < rhs.m_Data; + return lhs.m_Impl->dataPointer() < rhs.m_Impl->dataPointer(); + } + inline friend bool operator>(const ITensorItr& lhs, const ITensorItr& rhs) + { return rhs < lhs; } + inline friend bool operator<=(const ITensorItr& lhs, const ITensorItr& rhs) + { return !(lhs > rhs); } + inline friend bool operator>=(const ITensorItr& lhs, const ITensorItr& rhs) + { return !(lhs < rhs); } + + inline bool operator==(const ITensorItr& rhs) const + { + if (m_IsTrivial) return m_Data == rhs.m_Data; + return m_Impl->dataPointer() == rhs.m_Impl->dataPointer(); + } + inline bool operator!=(const ITensorItr& rhs) const + { return !operator==(rhs); } + + inline VALUE_REF operator[](size_t idx) + { + if (m_IsTrivial) return *(m_DataStart + idx); + return m_Impl->getReferenceAt(idx); + } + inline VALUE_REF operator*() + { if (m_IsTrivial) return *m_Data; else return m_Impl->getReference(); } + inline VALUE_REF operator->() + { return *(*this); } + inline float* dataPointer() const + { if (m_IsTrivial) return m_Data; else return m_Impl->dataPointer(); } + + +protected: + std::unique_ptr<::DlSystem::ITensorItrImpl> m_Impl; + bool m_IsTrivial = false; + float* m_Data = nullptr; + float* m_DataStart = nullptr; +}; + +}} + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif diff --git a/third_party/snpe/include/DlSystem/ITensorItrImpl.hpp b/third_party/snpe/include/DlSystem/ITensorItrImpl.hpp new file mode 100644 index 0000000000..069e7a1d69 --- /dev/null +++ b/third_party/snpe/include/DlSystem/ITensorItrImpl.hpp @@ -0,0 +1,42 @@ +//============================================================================= +// +// Copyright (c) 2015-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _ITENSOR_ITR_IMPL_HPP_ +#define _ITENSOR_ITR_IMPL_HPP_ + +#include "ZdlExportDefine.hpp" + +#include +#include + +namespace DlSystem +{ + class ITensorItrImpl; +} + +class ZDL_EXPORT DlSystem::ITensorItrImpl +{ +public: + ITensorItrImpl() {} + virtual ~ITensorItrImpl() {} + + virtual float getValue() const = 0; + virtual float& getReference() = 0; + virtual float& getReferenceAt(size_t idx) = 0; + virtual float* dataPointer() const = 0; + virtual void increment(int incVal = 1) = 0; + virtual void decrement(int decVal = 1) = 0; + virtual size_t getPosition() = 0; + virtual std::unique_ptr clone() = 0; + +private: + ITensorItrImpl& operator=(const ITensorItrImpl& other) = delete; + ITensorItrImpl(const ITensorItrImpl& other) = delete; +}; + +#endif diff --git a/third_party/snpe/include/DlSystem/IUDL.hpp b/third_party/snpe/include/DlSystem/IUDL.hpp new file mode 100644 index 0000000000..a171ac7e81 --- /dev/null +++ b/third_party/snpe/include/DlSystem/IUDL.hpp @@ -0,0 +1,105 @@ +//============================================================================= +// +// Copyright (c) 2016-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _DL_SYSTEM_IUDL_HPP_ +#define _DL_SYSTEM_IUDL_HPP_ + +#include "ZdlExportDefine.hpp" + +namespace zdl { +namespace DlSystem { + +/** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * Base class user concrete UDL implementation. + * + * All functions are marked as: + * + * - virtual + * - noexcept + * + * User should make sure no exceptions are propagated outside of + * their module. Errors can be communicated via return values. + */ +class ZDL_EXPORT IUDL { +public: + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * Destructor + */ + virtual ~IUDL() = default; + + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief Sets up the user's environment. + * This is called by the SNPE framework to allow the user the + * opportunity to setup anything which is needed for running + * user defined layers. + * + * @param cookie User provided opaque data returned by the SNPE + * runtime + * + * @param insz How many elements in input size array + * @param indim Pointer to a buffer that holds input dimension + * array + * @param indimsz Input dimension size array of the buffer + * 'indim'. Corresponds to indim + * + * @param outsz How many elements in output size array + * @param outdim Pointer to a buffer that holds output + * dimension array + * @param outdimsz Output dimension size of the buffer 'oudim'. + * Corresponds to indim + * + * @return true on success, false otherwise + */ + virtual bool setup(void *cookie, + size_t insz, const size_t **indim, const size_t *indimsz, + size_t outsz, const size_t **outdim, const size_t *outdimsz) = 0; + + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief Close the instance. Invoked by the SNPE + * framework to allow the user the opportunity to release any resources + * allocated during setup. + * + * @param cookie - User provided opaque data returned by the SNPE runtime + */ + virtual void close(void *cookie) noexcept = 0; + + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief Execute the user defined layer + * + * @param cookie User provided opaque data returned by the SNPE + * runtime + * + * @param input Const pointer to a float buffer that contains + * the input + * + * @param output Float pointer to a buffer that would hold + * the user defined layer's output. This buffer + * is allocated and owned by SNPE runtime. + */ + virtual bool execute(void *cookie, const float **input, float **output) = 0; +}; + +} // ns DlSystem + +} // ns zdl + +#endif // _DL_SYSTEM_IUDL_HPP_ diff --git a/third_party/snpe/include/DlSystem/IUserBuffer.hpp b/third_party/snpe/include/DlSystem/IUserBuffer.hpp new file mode 100644 index 0000000000..ea491a545b --- /dev/null +++ b/third_party/snpe/include/DlSystem/IUserBuffer.hpp @@ -0,0 +1,358 @@ +//============================================================================== +// +// Copyright (c) 2017-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _IUSER_BUFFER_HPP +#define _IUSER_BUFFER_HPP + +#include "TensorShape.hpp" +#include "ZdlExportDefine.hpp" +#include + +namespace zdl { +namespace DlSystem { + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + + +/** + * @brief . + * + * A base class buffer encoding type + */ +class ZDL_EXPORT UserBufferEncoding { +public: + + /** + * @brief . + * + * An enum class of all supported element types in a IUserBuffer + */ + enum class ElementType_t + { + /// Unknown element type. + UNKNOWN = 0, + + /// Each element is presented by float. + FLOAT = 1, + + /// Each element is presented by an unsigned int. + UNSIGNED8BIT = 2, + + /// Each element is presented by an 8-bit quantized value. + TF8 = 10, + + /// Each element is presented by an 16-bit quantized value. + TF16 = 11 + }; + + /** + * @brief Retrieves the size of the element, in bytes. + * + * @return Size of the element, in bytes. + */ + virtual size_t getElementSize() const noexcept = 0; + + /** + * @brief Retrieves the element type + * + * @return Element type + */ + ElementType_t getElementType() const noexcept {return m_ElementType;}; + + virtual ~UserBufferEncoding() {} + +protected: + UserBufferEncoding(ElementType_t elementType) : m_ElementType(elementType) {}; +private: + const ElementType_t m_ElementType; +}; + +/** + * @brief . + * + * A base class buffer source type + * + * @note User buffer from CPU support all kinds of runtimes; + * User buffer from GLBUFFER support only GPU runtime. + */ +class ZDL_EXPORT UserBufferSource { +public: + enum class SourceType_t + { + /// Unknown buffer source type. + UNKNOWN = 0, + + /// The network inputs are from CPU buffer. + CPU = 1, + + /// The network inputs are from OpenGL buffer. + GLBUFFER = 2 + }; + + /** + * @brief Retrieves the source type + * + * @return Source type + */ + SourceType_t getSourceType() const noexcept {return m_SourceType;}; + +protected: + UserBufferSource(SourceType_t sourceType): m_SourceType(sourceType) {}; +private: + const SourceType_t m_SourceType; +}; + +/** + * @brief . + * + * An source type where input data is delivered from OpenGL buffer + */ +class ZDL_EXPORT UserBufferSourceGLBuffer : public UserBufferSource{ +public: + UserBufferSourceGLBuffer() : UserBufferSource(SourceType_t::GLBUFFER) {}; +}; + +/** + * @brief . + * + * An encoding type where each element is represented by an unsigned int + */ +class ZDL_EXPORT UserBufferEncodingUnsigned8Bit : public UserBufferEncoding { +public: + UserBufferEncodingUnsigned8Bit() : UserBufferEncoding(ElementType_t::UNSIGNED8BIT) {}; + size_t getElementSize() const noexcept override; + +protected: + UserBufferEncodingUnsigned8Bit(ElementType_t elementType) : UserBufferEncoding(elementType) {}; + +}; + +/** + * @brief . + * + * An encoding type where each element is represented by a float + */ +class ZDL_EXPORT UserBufferEncodingFloat : public UserBufferEncoding { +public: + UserBufferEncodingFloat() : UserBufferEncoding(ElementType_t::FLOAT) {}; + size_t getElementSize() const noexcept override; + +}; + +/** + * @brief . + * + * An encoding type where each element is represented by tf8, which is an + * 8-bit quantizd value, which has an exact representation of 0.0 + */ +class ZDL_EXPORT UserBufferEncodingTfN : public UserBufferEncoding { +public: + UserBufferEncodingTfN() = delete; + UserBufferEncodingTfN(uint64_t stepFor0, float stepSize, uint8_t bWidth=8): + UserBufferEncoding(getTypeFromWidth(bWidth)), + bitWidth(bWidth), + m_StepExactly0(stepFor0), + m_QuantizedStepSize(stepSize){}; + + UserBufferEncodingTfN(const zdl::DlSystem::UserBufferEncoding &ubEncoding) : UserBufferEncoding(ubEncoding.getElementType()){ + const zdl::DlSystem::UserBufferEncodingTfN* ubEncodingTfN + = dynamic_cast (&ubEncoding); + if (ubEncodingTfN) { + m_StepExactly0 = ubEncodingTfN->getStepExactly0(); + m_QuantizedStepSize = ubEncodingTfN->getQuantizedStepSize(); + bitWidth = ubEncodingTfN->bitWidth; + } + } + + size_t getElementSize() const noexcept override; + /** + * @brief Sets the step value that represents 0 + * + * @param[in] stepExactly0 The step value that represents 0 + * + */ + void setStepExactly0(uint64_t stepExactly0) { + m_StepExactly0 = stepExactly0; + } + + /** + * @brief Sets the float value that each step represents + * + * @param[in] quantizedStepSize The float value of each step size + * + */ + void setQuantizedStepSize(const float quantizedStepSize) { + m_QuantizedStepSize = quantizedStepSize; + } + + /** + * @brief Retrieves the step that represents 0.0 + * + * @return Step value + */ + uint64_t getStepExactly0() const { + return m_StepExactly0; + } + + /** + * Calculates the minimum floating point value that + * can be represented with this encoding. + * + * @return Minimum representable floating point value + */ + float getMin() const { + return static_cast(m_QuantizedStepSize * (0 - (double)m_StepExactly0)); + } + + /** + * Calculates the maximum floating point value that + * can be represented with this encoding. + * + * @return Maximum representable floating point value + */ + float getMax() const{ + return static_cast(m_QuantizedStepSize * (pow(2,bitWidth)-1 - (double)m_StepExactly0)); + }; + + /** + * @brief Retrieves the step size + * + * @return Step size + */ + float getQuantizedStepSize() const { + return m_QuantizedStepSize; + } + + ElementType_t getTypeFromWidth(uint8_t width); + + uint8_t bitWidth; +protected: + uint64_t m_StepExactly0; + float m_QuantizedStepSize; +}; + + +class ZDL_EXPORT UserBufferEncodingTf8 : public UserBufferEncodingTfN { +public: + UserBufferEncodingTf8() = delete; + UserBufferEncodingTf8(unsigned char stepFor0, float stepSize) : + UserBufferEncodingTfN(stepFor0, stepSize) {}; + + UserBufferEncodingTf8(const zdl::DlSystem::UserBufferEncoding &ubEncoding) : UserBufferEncodingTfN(ubEncoding){} + +/** + * @brief Sets the step value that represents 0 + * + * @param[in] stepExactly0 The step value that represents 0 + * + */ + + void setStepExactly0(const unsigned char stepExactly0) { + UserBufferEncodingTfN::m_StepExactly0 = stepExactly0; + } + +/** + * @brief Retrieves the step that represents 0.0 + * + * @return Step value + */ + + unsigned char getStepExactly0() const { + return UserBufferEncodingTfN::m_StepExactly0; + } + +}; + + +/** + * @brief UserBuffer contains a pointer and info on how to walk it and interpret its content. + */ +class ZDL_EXPORT IUserBuffer { +public: + virtual ~IUserBuffer() = default; + + /** + * @brief Retrieves the total number of bytes between elements in each dimension if + * the buffer were to be interpreted as a multi-dimensional array. + * + * @return Number of bytes between elements in each dimension. + * e.g. A tightly packed tensor of floats with dimensions [4, 3, 2] would + * return strides of [24, 8, 4]. + */ + virtual const TensorShape& getStrides() const = 0; + + /** + * @brief Retrieves the size of the buffer, in bytes. + * + * @return Size of the underlying buffer, in bytes. + */ + virtual size_t getSize() const = 0; + + /** + * @brief Retrieves the size of the inference data in the buffer, in bytes. + * + * The inference results from a dynamic-sized model may not be exactly the same size + * as the UserBuffer provided to SNPE. This function can be used to get the amount + * of output inference data, which may be less or greater than the size of the UserBuffer. + * + * If the inference results fit in the UserBuffer, getOutputSize() would be less than + * or equal to getSize(). But if the inference results were more than the capacity of + * the provided UserBuffer, the results would be truncated to fit the UserBuffer. But, + * getOutputSize() would be greater than getSize(), which indicates a bigger buffer + * needs to be provided to SNPE to hold all of the inference results. + * + * @return Size required for the buffer to hold all inference results, which can be less + * or more than the size of the buffer, in bytes. + */ + virtual size_t getOutputSize() const = 0; + + /** + * @brief Changes the underlying memory that backs the UserBuffer. + * + * This can be used to avoid creating multiple UserBuffer objects + * when the only thing that differs is the memory location. + * + * @param[in] buffer Pointer to the memory location + * + * @return Whether the set succeeds. + */ + virtual bool setBufferAddress(void *buffer) noexcept = 0; + + /** + * @brief Gets a const reference to the data encoding object of + * the underlying buffer + * + * This is necessary when the UserBuffer is filled by SNPE with + * data types such as TF8, where the caller needs to know the quantization + * parameters in order to interpret the data properly + * + * @return A read-only encoding object + */ + virtual const UserBufferEncoding& getEncoding() const noexcept = 0; + + /** + * @brief Gets a reference to the data encoding object of + * the underlying buffer + * + * This is necessary when the UserBuffer is re-used, and the encoding + * parameters can change. For example, each input can be quantized with + * different step sizes. + * + * @return Data encoding meta-data + */ + virtual UserBufferEncoding& getEncoding() noexcept = 0; + +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} +} + +#endif diff --git a/third_party/snpe/include/DlSystem/IUserBufferFactory.hpp b/third_party/snpe/include/DlSystem/IUserBufferFactory.hpp new file mode 100644 index 0000000000..59803fbd8f --- /dev/null +++ b/third_party/snpe/include/DlSystem/IUserBufferFactory.hpp @@ -0,0 +1,81 @@ +//============================================================================= +// +// Copyright (c) 2017 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _IUSERBUFFER_FACTORY_HPP +#define _IUSERBUFFER_FACTORY_HPP + +#include "IUserBuffer.hpp" +#include "TensorShape.hpp" +#include "ZdlExportDefine.hpp" +#include "DlEnums.hpp" +namespace zdl { + namespace DlSystem { + class IUserBuffer; + + class TensorShape; + } +} + +namespace zdl { +namespace DlSystem { + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** +* Factory interface class to create IUserBuffer objects. +*/ +class ZDL_EXPORT IUserBufferFactory { +public: + virtual ~IUserBufferFactory() = default; + + /** + * @brief Creates a UserBuffer + * + * @param[in] buffer Pointer to the buffer that the caller supplies + * + * @param[in] bufSize Buffer size, in bytes + * + * @param[in] strides Total number of bytes between elements in each dimension. + * E.g. A tightly packed tensor of floats with dimensions [4, 3, 2] would have strides of [24, 8, 4]. + * + * @param[in] userBufferEncoding Reference to an UserBufferEncoding object + * + * @note Caller has to ensure that memory pointed to by buffer stays accessible + * for the lifetime of the object created + */ + virtual std::unique_ptr + createUserBuffer(void *buffer, size_t bufSize, const zdl::DlSystem::TensorShape &strides, zdl::DlSystem::UserBufferEncoding* userBufferEncoding) noexcept = 0; + + /** + * @brief Creates a UserBuffer + * + * @param[in] buffer Pointer to the buffer that the caller supplies + * + * @param[in] bufSize Buffer size, in bytes + * + * @param[in] strides Total number of bytes between elements in each dimension. + * E.g. A tightly packed tensor of floats with dimensions [4, 3, 2] would have strides of [24, 8, 4]. + * + * @param[in] userBufferEncoding Reference to an UserBufferEncoding object + * + * @param[in] userBufferSource Reference to an UserBufferSource object + * + * @note Caller has to ensure that memory pointed to by buffer stays accessible + * for the lifetime of the object created + */ + virtual std::unique_ptr + createUserBuffer(void *buffer, size_t bufSize, const zdl::DlSystem::TensorShape &strides, zdl::DlSystem::UserBufferEncoding* userBufferEncoding, zdl::DlSystem::UserBufferSource* userBufferSource) noexcept = 0; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} +} + + +#endif diff --git a/third_party/snpe/include/DlSystem/PlatformConfig.hpp b/third_party/snpe/include/DlSystem/PlatformConfig.hpp new file mode 100644 index 0000000000..c7b85f43c1 --- /dev/null +++ b/third_party/snpe/include/DlSystem/PlatformConfig.hpp @@ -0,0 +1,230 @@ +//============================================================================= +// +// Copyright (c) 2017-2018,2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef _DL_SYSTEM_PLATFORM_CONFIG_HPP_ +#define _DL_SYSTEM_PLATFORM_CONFIG_HPP_ + +#include "DlSystem/ZdlExportDefine.hpp" +#include + +namespace zdl{ +namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + + +/** + * @brief . + * + * A structure OpenGL configuration + * + * @note When certain OpenGL context and display are provided to UserGLConfig for using + * GPU buffer as input directly, the user MUST ensure the particular OpenGL + * context and display remain vaild throughout the execution of neural network models. + */ +struct ZDL_EXPORT UserGLConfig +{ + /// Holds user EGL context. + /// + void* userGLContext = nullptr; + + /// Holds user EGL display. + void* userGLDisplay = nullptr; +}; + +/** + * @brief . + * + * A structure Gpu configuration + */ +struct ZDL_EXPORT UserGpuConfig{ + /// Holds user OpenGL configuration. + /// + UserGLConfig userGLConfig; +}; + +/** + * @brief . + * + * A class user platform configuration + */ +class ZDL_EXPORT PlatformConfig +{ +public: + + /** + * @brief . + * + * An enum class of all supported platform types + */ + enum class PlatformType_t + { + /// Unknown platform type. + UNKNOWN = 0, + + /// Snapdragon CPU. + CPU = 1, + + /// Adreno GPU. + GPU = 2, + + /// Hexagon DSP. + DSP = 3 + }; + + /** + * @brief . + * + * A union class user platform configuration information + */ + union PlatformConfigInfo + { + /// Holds user GPU Configuration. + /// + UserGpuConfig userGpuConfig; + + PlatformConfigInfo(){}; + }; + + PlatformConfig() : m_PlatformType(PlatformType_t::UNKNOWN), + m_PlatformOptions("") {}; + + /** + * @brief Retrieves the platform type + * + * @return Platform type + */ + PlatformType_t getPlatformType() const {return m_PlatformType;}; + + /** + * @brief Indicates whther the plaform configuration is valid. + * + * @return True if the platform configuration is valid; false otherwise. + */ + bool isValid() const {return (PlatformType_t::UNKNOWN != m_PlatformType);}; + + /** + * @brief Retrieves the Gpu configuration + * + * @param[out] userGpuConfig The passed in userGpuConfig populated with the Gpu configuration on return. + * + * @return True if Gpu configuration was retrieved; false otherwise. + */ + bool getUserGpuConfig(UserGpuConfig& userGpuConfig) const + { + if(m_PlatformType == PlatformType_t::GPU) + { + userGpuConfig = m_PlatformConfigInfo.userGpuConfig; + return true; + } + else + { + return false; + } + } + + /** + * @brief Sets the Gpu configuration + * + * @param[in] userGpuConfig Gpu Configuration + * + * @return True if Gpu configuration was successfully set; false otherwise. + */ + bool setUserGpuConfig(UserGpuConfig& userGpuConfig) + { + if((userGpuConfig.userGLConfig.userGLContext != nullptr) && (userGpuConfig.userGLConfig.userGLDisplay != nullptr)) + { + switch (m_PlatformType) + { + case PlatformType_t::GPU: + m_PlatformConfigInfo.userGpuConfig = userGpuConfig; + return true; + case PlatformType_t::UNKNOWN: + m_PlatformType = PlatformType_t::GPU; + m_PlatformConfigInfo.userGpuConfig = userGpuConfig; + return true; + default: + return false; + } + } + else + return false; + } + + /** + * @brief Sets the platform options + * + * @param[in] options Options as a string in the form of "keyword:options" + * + * @return True if options are pass validation; otherwise false. If false, the options are not updated. + */ + bool setPlatformOptions(std::string options) { + std::string oldOptions = m_PlatformOptions; + m_PlatformOptions = options; + if (isOptionsValid()) { + return true; + } else { + m_PlatformOptions = oldOptions; + return false; + } + } + + /** + * @brief Indicates whther the plaform configuration is valid. + * + * @return True if the platform configuration is valid; false otherwise. + */ + bool isOptionsValid() const; + + /** + * @brief Gets the platform options + * + * @return Options as a string + */ + std::string getPlatformOptions() const { return m_PlatformOptions; } + + /** + * @brief Sets the platform options + * + * @param[in] optionName Name of platform options" + * @param[in] value Value of specified optionName + * + * @return If true, add "optionName:value" to platform options if optionName don't exist, otherwise update the + * value of specified optionName. + * If false, the platform options will not be changed. + */ + bool setPlatformOptionValue(const std::string& optionName, const std::string& value); + + /** + * @brief Removes the platform options + * + * @param[in] optionName Name of platform options" + * @param[in] value Value of specified optionName + * + * @return If true, removed "optionName:value" to platform options if optionName don't exist, do nothing. + * If false, the platform options will not be changed. + */ + bool removePlatformOptionValue(const std::string& optionName, const std::string& value); + + static void SetIsUserGLBuffer(bool isUserGLBuffer); + static bool GetIsUserGLBuffer(); + +private: + PlatformType_t m_PlatformType; + PlatformConfigInfo m_PlatformConfigInfo; + std::string m_PlatformOptions; + static bool m_IsUserGLBuffer; +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +}} //namespace end + +#endif diff --git a/third_party/snpe/include/DlSystem/RuntimeList.hpp b/third_party/snpe/include/DlSystem/RuntimeList.hpp new file mode 100644 index 0000000000..1088a5b31f --- /dev/null +++ b/third_party/snpe/include/DlSystem/RuntimeList.hpp @@ -0,0 +1,154 @@ +//============================================================================= +// +// Copyright (c) 2019 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#include "ZdlExportDefine.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/StringList.hpp" +#include +#include + +#ifndef DL_SYSTEM_RUNTIME_LIST_HPP +#define DL_SYSTEM_RUNTIME_LIST_HPP + +namespace DlSystem +{ + // Forward declaration of Runtime List implementation. + class RuntimeListImpl; +} + +namespace zdl +{ +namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing list of runtimes + */ +class ZDL_EXPORT RuntimeList final +{ +public: + + /** + * @brief . + * + * Creates a new runtime list + * + */ + RuntimeList(); + + /** + * @brief . + * + * copy constructor. + * @param[in] other object to copy. + */ + RuntimeList(const RuntimeList& other); + + /** + * @brief . + * + * constructor with single Runtime_t object + * @param[in] Runtime_t object + */ + RuntimeList(const zdl::DlSystem::Runtime_t& runtime); + + /** + * @brief . + * + * assignment operator. + */ + RuntimeList& operator=(const RuntimeList& other); + + /** + * @brief . + * + * subscript operator. + */ + Runtime_t& operator[](size_t index); + + /** + * @brief Adds runtime to the end of the runtime list + * order of precedence is former followed by latter entry + * + * @param[in] runtime to add + * + * Ruturns false If the runtime already exists + */ + bool add(const zdl::DlSystem::Runtime_t& runtime); + + /** + * @brief Removes the runtime from the list + * + * @param[in] runtime to be removed + * + * @note If the runtime is not found, nothing is done. + */ + void remove(const zdl::DlSystem::Runtime_t runtime) noexcept; + + /** + * @brief Returns the number of runtimes in the list + */ + size_t size() const noexcept; + + /** + * @brief Returns true if the list is empty + */ + bool empty() const noexcept; + + /** + * @brief . + * + * Removes all runtime from the list + */ + void clear() noexcept; + + /** + * @brief . + * + * Returns a StringList of names from the runtime list in + * order of precedence + */ + zdl::DlSystem::StringList getRuntimeListNames() const; + + /** + * @brief . + * + * @param[in] runtime string + * Returns a Runtime enum corresponding to the in param string + * + */ + static zdl::DlSystem::Runtime_t stringToRuntime(const char* runtimeStr); + + /** + * @brief . + * + * @param[in] runtime + * Returns a string corresponding to the in param runtime enum + * + */ + static const char* runtimeToString(const zdl::DlSystem::Runtime_t runtime); + + ~RuntimeList(); + +private: + void deepCopy(const RuntimeList &other); + std::unique_ptr<::DlSystem::RuntimeListImpl> m_RuntimeListImpl; +}; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // DL_SYSTEM_RUNTIME_LIST_HPP + diff --git a/third_party/snpe/include/DlSystem/String.hpp b/third_party/snpe/include/DlSystem/String.hpp new file mode 100644 index 0000000000..c1eba3bad9 --- /dev/null +++ b/third_party/snpe/include/DlSystem/String.hpp @@ -0,0 +1,104 @@ +//============================================================================= +// +// Copyright (c) 2017, 2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#ifndef PLATFORM_STANDARD_STRING_HPP +#define PLATFORM_STANDARD_STRING_HPP + +#include +#include +#include +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl +{ +namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * Class for wrapping char * as a really stripped down std::string replacement. + */ +class ZDL_EXPORT String final +{ +public: + String() = delete; + + /** + * Construct a string from std::string reference. + * @param str Reference to a std::string + */ + explicit String(const std::string& str); + + /** + * Construct a string from char* reference. + * @param a char* + */ + explicit String(const char* str); + + /** + * move constructor. + */ + String(String&& other) noexcept; + + /** + * copy constructor. + */ + String(const String& other) = delete; + + /** + * assignment operator. + */ + String& operator=(const String&) = delete; + + /** + * move assignment operator. + */ + String& operator=(String&&) = delete; + + /** + * class comparators + */ + bool operator<(const String& rhs) const noexcept; + bool operator>(const String& rhs) const noexcept; + bool operator<=(const String& rhs) const noexcept; + bool operator>=(const String& rhs) const noexcept; + bool operator==(const String& rhs) const noexcept; + bool operator!=(const String& rhs) const noexcept; + + /** + * class comparators against std::string + */ + bool operator<(const std::string& rhs) const noexcept; + bool operator>(const std::string& rhs) const noexcept; + bool operator<=(const std::string& rhs) const noexcept; + bool operator>=(const std::string& rhs) const noexcept; + bool operator==(const std::string& rhs) const noexcept; + bool operator!=(const std::string& rhs) const noexcept; + + const char* c_str() const noexcept; + + ~String(); +private: + + char* m_string; +}; + +/** + * overloaded << operator + */ +ZDL_EXPORT std::ostream& operator<<(std::ostream& os, const String& str) noexcept; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // PLATFORM_STANDARD_STRING_HPP diff --git a/third_party/snpe/include/DlSystem/StringList.hpp b/third_party/snpe/include/DlSystem/StringList.hpp new file mode 100644 index 0000000000..a9a7d5ed89 --- /dev/null +++ b/third_party/snpe/include/DlSystem/StringList.hpp @@ -0,0 +1,107 @@ +//============================================================================= +// +// Copyright (c) 2016 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include "ZdlExportDefine.hpp" + +#ifndef DL_SYSTEM_STRINGLIST_HPP +#define DL_SYSTEM_STRINGLIST_HPP + +namespace zdl +{ +namespace DlSystem +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * Class for holding an order list of null-terminated ASCII strings. + */ +class ZDL_EXPORT StringList final +{ +public: + StringList() {} + + /** + * Construct a string list with some pre-allocated memory. + * @warning Contents of the list will be uninitialized + * @param[in] length Number of elements for which to pre-allocate space. + */ + explicit StringList(size_t length); + + /** + * Append a string to the list. + * @param[in] str Null-terminated ASCII string to append to the list. + */ + void append(const char* str); + + /** + * Returns the string at the indicated position, + * or an empty string if the positions is greater than the size + * of the list. + * @param[in] idx Position in the list of the desired string + */ + const char* at(size_t idx) const noexcept; + + /** + * Pointer to the first string in the list. + * Can be used to iterate through the list. + */ + const char** begin() const noexcept; + + /** + * Pointer to one after the last string in the list. + * Can be used to iterate through the list. + */ + const char** end() const noexcept; + + /** + * Return the number of valid string pointers held by this list. + */ + size_t size() const noexcept; + + + /** + * assignment operator. + */ + StringList& operator=(const StringList&) noexcept; + + /** + * copy constructor. + * @param[in] other object to copy. + */ + StringList(const StringList& other); + + /** + * move constructor. + * @param[in] other object to move. + */ + StringList(StringList&& other) noexcept; + + ~StringList(); +private: + void copy(const StringList& other); + + void resize(size_t length); + + void clear(); + + static const char* s_Empty; + const char** m_Strings = nullptr; + const char** m_End = nullptr; + size_t m_Size = 0; +}; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // DL_SYSTEM_STRINGLIST_HPP + diff --git a/third_party/snpe/include/DlSystem/TensorMap.hpp b/third_party/snpe/include/DlSystem/TensorMap.hpp new file mode 100644 index 0000000000..feecec6667 --- /dev/null +++ b/third_party/snpe/include/DlSystem/TensorMap.hpp @@ -0,0 +1,120 @@ +//============================================================================= +// +// Copyright (c) 2016 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include "ZdlExportDefine.hpp" +#include "ITensor.hpp" +#include "StringList.hpp" + +#ifndef DL_SYSTEM_TENSOR_MAP_HPP +#define DL_SYSTEM_TENSOR_MAP_HPP + +namespace DlSystem +{ + // Forward declaration of tensor map implementation. + class TensorMapImpl; +} + +namespace zdl +{ +namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing the map of tensor. + */ +class ZDL_EXPORT TensorMap final +{ +public: + + /** + * @brief . + * + * Creates a new empty tensor map + */ + TensorMap(); + + /** + * copy constructor. + * @param[in] other object to copy. + */ + TensorMap(const TensorMap& other); + + /** + * assignment operator. + */ + TensorMap& operator=(const TensorMap& other); + + /** + * @brief Adds a name and the corresponding tensor pointer + * to the map + * + * @param[in] name The name of the tensor + * @param[out] tensor The pointer to the tensor + * + * @note If a tensor with the same name already exists, the + * tensor is replaced with the existing tensor. + */ + void add(const char *name, zdl::DlSystem::ITensor *tensor); + + /** + * @brief Removes a mapping of tensor and its name by its name + * + * @param[in] name The name of tensor to be removed + * + * @note If no tensor with the specified name is found, nothing + * is done. + */ + void remove(const char *name) noexcept; + + /** + * @brief Returns the number of tensors in the map + */ + size_t size() const noexcept; + + /** + * @brief . + * + * Removes all tensors from the map + */ + void clear() noexcept; + + /** + * @brief Returns the tensor given its name. + * + * @param[in] name The name of the tensor to get. + * + * @return nullptr if no tensor with the specified name is + * found; otherwise, a valid pointer to the tensor. + */ + zdl::DlSystem::ITensor* getTensor(const char *name) const noexcept; + + /** + * @brief . + * + * Returns the names of all tensors + */ + zdl::DlSystem::StringList getTensorNames() const; + + ~TensorMap(); +private: + void swap(const TensorMap &other); + std::unique_ptr<::DlSystem::TensorMapImpl> m_TensorMapImpl; +}; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // DL_SYSTEM_TENSOR_MAP_HPP + diff --git a/third_party/snpe/include/DlSystem/TensorShape.hpp b/third_party/snpe/include/DlSystem/TensorShape.hpp new file mode 100644 index 0000000000..99583dccb4 --- /dev/null +++ b/third_party/snpe/include/DlSystem/TensorShape.hpp @@ -0,0 +1,203 @@ +//============================================================================= +// +// Copyright (c) 2016 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include +#include +#include +#include "ZdlExportDefine.hpp" + +#ifndef DL_SYSTEM_TENSOR_SHAPE_HPP +#define DL_SYSTEM_TENSOR_SHAPE_HPP + +namespace DlSystem +{ + // Forward declaration of tensor shape implementation. + class TensorShapeImpl; +} + +namespace zdl +{ +namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * Convenient typedef to represent dimension + */ +using Dimension = size_t; + +/** + * @brief . + * + * A class representing the shape of tensor. It is used at the + * time of creation of tensor. + */ +class ZDL_EXPORT TensorShape final +{ +public: + + /** + * @brief . + * + * Creates a new shape with a list of dims specified in + * initializer list fashion. + * + * @param[in] dims The dimensions are specified in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + */ + TensorShape(std::initializer_list dims); + + /** + * @brief . + * + * Creates a new shape with a list of dims specified in array + * + * @param[in] dims The dimensions are specified in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + * @param[in] size Size of the array. + * + */ + TensorShape(const Dimension *dims, size_t size); + + /** + * @brief . + * + * Creates a new shape with a vector of dims specified in + * vector fashion. + * + * @param[in] dims The dimensions are specified in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + */ + TensorShape(std::vector dims); + + /** + * @brief . + * + * copy constructor. + * @param[in] other object to copy. + */ + TensorShape(const TensorShape& other); + + /** + * @brief . + * + * assignment operator. + */ + TensorShape& operator=(const TensorShape& other); + + /** + * @brief . + * + * Creates a new shape with no dims. It can be extended later + * by invoking concatenate. + */ + TensorShape(); + + /** + * @brief . + * + * Concatenates additional dimensions specified in + * initializer list fashion to the existing dimensions. + * + * @param[in] dims The dimensions are specified in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + */ + void concatenate(std::initializer_list dims); + + /** + * @brief . + * + * Concatenates additional dimensions specified in + * the array to the existing dimensions. + * + * @param[in] dims The dimensions are specified in which the last + * element of the vector represents the fastest varying + * dimension and the zeroth element represents the slowest + * varying, etc. + * + * @param[in] size Size of the array. + * + */ + void concatenate(const Dimension *dims, size_t size); + + /** + * @brief . + * + * Concatenates an additional dimension to the existing + * dimensions. + * + * @param[in] dim The dimensions are specified in which the last element + * of the vector represents the fastest varying dimension and the + * zeroth element represents the slowest varying, etc. + * + */ + void concatenate(const Dimension &dim); + + /** + * @brief . + * + * Retrieves a single dimension, based on its index. + * + * @return The value of dimension + * + * @throws std::out_of_range if the index is >= the number of + * dimensions (or rank). + */ + Dimension& operator[](size_t index); + Dimension& operator[](size_t index) const; + + /** + * @brief . + * + * Retrieves the rank i.e. number of dimensions. + * + * @return The rank + */ + size_t rank() const; + + /** + * @brief . + * + * Retrieves a pointer to the first dimension of shape + * + * @return nullptr if no dimension exists; otherwise, points to + * the first dimension. + * + */ + const Dimension* getDimensions() const; + + ~TensorShape(); + +private: + void swap(const TensorShape &other); + std::unique_ptr<::DlSystem::TensorShapeImpl> m_TensorShapeImpl; +}; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // DL_SYSTEM_TENSOR_SHAPE_HPP + diff --git a/third_party/snpe/include/DlSystem/TensorShapeMap.hpp b/third_party/snpe/include/DlSystem/TensorShapeMap.hpp new file mode 100644 index 0000000000..cef946e2e6 --- /dev/null +++ b/third_party/snpe/include/DlSystem/TensorShapeMap.hpp @@ -0,0 +1,127 @@ +//============================================================================= +// +// Copyright (c) 2017-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include +#include +#include "ZdlExportDefine.hpp" +#include "DlSystem/TensorShape.hpp" +#include "DlSystem/StringList.hpp" + +#ifndef DL_SYSTEM_TENSOR_SHAPE_MAP_HPP +#define DL_SYSTEM_TENSOR_SHAPE_MAP_HPP + +namespace DlSystem +{ + // Forward declaration of tensor shape map implementation. + class TensorShapeMapImpl; +} + +namespace zdl +{ +namespace DlSystem +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing the map of names and tensorshapes. + */ +class ZDL_EXPORT TensorShapeMap final +{ +public: + + /** + * @brief . + * + * Creates a new tensor shape map + * + */ + TensorShapeMap(); + + /** + * @brief . + * + * copy constructor. + * @param[in] other object to copy. + */ + TensorShapeMap(const TensorShapeMap& other); + + /** + * @brief . + * + * assignment operator. + */ + TensorShapeMap& operator=(const TensorShapeMap& other); + + /** + * @brief Adds a name and the corresponding tensor pointer + * to the map + * + * @param[in] name The name of the tensor + * @param[out] tensor The pointer to the tensor + * + * @note If a tensor with the same name already exists, no new + * tensor is added. + */ + void add(const char *name, const zdl::DlSystem::TensorShape& tensorShape); + + /** + * @brief Removes a mapping of tensor and its name by its name + * + * @param[in] name The name of tensor to be removed + * + * @note If no tensor with the specified name is found, nothing + * is done. + */ + void remove(const char *name) noexcept; + + /** + * @brief Returns the number of tensors in the map + */ + size_t size() const noexcept; + + /** + * @brief . + * + * Removes all tensors from the map + */ + void clear() noexcept; + + /** + * @brief Returns the tensor given its name. + * + * @param[in] name The name of the tensor to get. + * + * @return nullptr if no tensor with the specified name is + * found; otherwise, a valid pointer to the tensor. + */ + zdl::DlSystem::TensorShape getTensorShape(const char *name) const noexcept; + + /** + * @brief . + * + * Returns the names of all tensor shapes + */ + zdl::DlSystem::StringList getTensorShapeNames() const; + + ~TensorShapeMap(); +private: + void swap(const TensorShapeMap &other); + std::unique_ptr<::DlSystem::TensorShapeMapImpl> m_TensorShapeMapImpl; +}; + +} // DlSystem namespace +} // zdl namespace + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // DL_SYSTEM_TENSOR_SHAPE_MAP_HPP + diff --git a/third_party/snpe/include/DlSystem/UDLContext.hpp b/third_party/snpe/include/DlSystem/UDLContext.hpp new file mode 100644 index 0000000000..21fce1b04a --- /dev/null +++ b/third_party/snpe/include/DlSystem/UDLContext.hpp @@ -0,0 +1,243 @@ +//============================================================================== +// +// Copyright (c) 2016-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef UDL_CONTEXT_HPP +#define UDL_CONTEXT_HPP + +#include // memset +#include + +#include "ZdlExportDefine.hpp" + +namespace zdl { namespace DlSystem { + +/** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * UDLContext holds the user defined layer context which + * consists of a layer name, layer ID, blob and blob size. + * + * An instance of UDLContext is passed as an argument to the + * UDLFactoryFunc provided by the user every time the SNPE + * runtime encounters an unknown layer descriptor. The instance + * of a UDLContext is created by the SNPE runtime and is + * consumed by the user's factory function. The user should + * obtain a copy of this class and should not assume any + * prolonged object lifetime beyond the UDLFactoryFunction. + */ +class ZDL_EXPORT UDLContext final { +public: + /** + * @brief Constructor + * + * @param[in] name name of the layer + * + * @param[in] type layer type + * + * @param[in] id identifier for the layer + * + * @param[in] id Blob/bytes as packed by the user code as part of + * the Python converter script + */ + UDLContext(const std::string& name, + const std::string& type, + int32_t id, + const std::string& blob) : + m_Name(name), m_Type(type), m_Size(blob.size()), m_Id(id) { + // FIXME not dealing with alloc error + m_Buffer = new uint8_t[m_Size]; + std::memcpy(m_Buffer, blob.data(), m_Size); + } + + /** + * @brief . + * + * Empty constructor is useful for + * creating an empty UDLContext and then run copy constructor + * from a fully initialized one. + */ + explicit UDLContext() {} + + /** + * @brief . + * + * destructor Deallocates any internal allocated memory + */ + ~UDLContext() { release(); } + + /** + * @brief . + * + * Deallocate any internally allocated memory + */ + void release() { + if (m_Buffer && m_Size) + std::memset(m_Buffer, 0, m_Size); + delete []m_Buffer; + m_Buffer = nullptr; + m_Size = 0; + } + + /** + * @brief . + * + * Copy Constructor - makes a copy from ctx + * + * @param[in] ctx Source UDLContext to copy from + */ + UDLContext(const UDLContext& ctx) : m_Name(ctx.m_Name), + m_Type(ctx.m_Type), + m_Id(ctx.m_Id) { + std::tuple cpy = ctx.getCopy(); + // current compiler does not support get + m_Buffer = std::get<0>(cpy); + m_Size = std::get<1>(cpy); + } + + /** + * @brief + * + * Assignment operator - makes a copy from ctx + * + * @param[in] ctx Source UDLContext to copy from + * + * @return this + */ + UDLContext& operator=(const UDLContext& ctx) { + UDLContext c (ctx); + this->swap(c); // non throwing swap + return *this; + } + + /** + * @brief . + * + * Move Constructor - Move internals from ctx into this + * + * @param[in] ctx Source UDLContext to move from + */ + UDLContext(UDLContext&& ctx) : + m_Name(std::move(ctx.m_Name)), + m_Type(std::move(ctx.m_Type)), + m_Buffer(ctx.m_Buffer), + m_Size(ctx.m_Size), + m_Id(ctx.m_Id) { + ctx.clear(); + } + + /** + * @brief . + * + * Assignment move - Move assignment operator from ctx + * + * @param[in] ctx Source UDLContext to move from + * + * @return this + */ + UDLContext& operator=(UDLContext&& ctx) { + m_Name = std::move(ctx.m_Name); + m_Type = std::move(ctx.m_Type); + m_Buffer = ctx.m_Buffer; + m_Size = ctx.m_Size; + m_Id = ctx.m_Id; + ctx.clear(); + return *this; + } + + /** + * @brief . + * + * Obtain the name of the layer + * + * @return const reference to the name of the layer + */ + const std::string& getName() const noexcept { return m_Name; } + + /** + * @brief . + * + * Obtain the type of the layer + * + * @return const reference to the type of the layer + */ + const std::string& getType() const noexcept { return m_Type; } + + /** + * @brief . + * + * Obtain the Id of the layer + * + * @return The id of the layer + */ + int32_t getId() const noexcept { return m_Id; } + + /** + * @brief . + * + * Obtain the size of the blob + * + * @return Size of the internal blob + */ + size_t getSize() const noexcept { return m_Size; } + + /** + * @brief . + * + * Get a const pointer to the internal blob + * + * @return Const pointer to the internal blob + */ + const uint8_t* getBlob() const noexcept { return m_Buffer; } + + /** + * @brief . + * + * Get a copy of the blob/size into a tuple + * + * @return A tuple with a pointer to a copy of the blob and a + * size + */ + std::tuple getCopy() const { + uint8_t* buf = new uint8_t[m_Size]; + // FIXME missing memcpy + std::memcpy(buf, m_Buffer, m_Size); + return std::make_tuple(buf, m_Size); + } + + /** + * @brief . + * + * Set zeros in the internals members + */ + void clear() { + m_Name.clear(); + m_Type.clear(); + m_Buffer = 0; + m_Size = 0; + m_Id = -1; + } +private: + void swap(UDLContext& c) noexcept { + std::swap(m_Name, c.m_Name); + std::swap(m_Type, c.m_Type); + std::swap(m_Id, c.m_Id); + std::swap(m_Buffer, c.m_Buffer); + std::swap(m_Size, c.m_Size); + } + std::string m_Name; // name of the layer instance + std::string m_Type; // The actual layer type + uint8_t* m_Buffer = nullptr; + size_t m_Size = 0; + int32_t m_Id = -1; +}; + +}} + +#endif /* UDL_CONTEXT_HPP */ diff --git a/third_party/snpe/include/DlSystem/UDLFunc.hpp b/third_party/snpe/include/DlSystem/UDLFunc.hpp new file mode 100644 index 0000000000..6a95eef170 --- /dev/null +++ b/third_party/snpe/include/DlSystem/UDLFunc.hpp @@ -0,0 +1,87 @@ +//============================================================================== +// +// Copyright (c) 2015-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _UDL_FUNC_HPP_ +#define _UDL_FUNC_HPP_ + +#include + +#include "ZdlExportDefine.hpp" +#include + +namespace zdl { + namespace DlSystem { + class UDLContext; + } +} + +namespace zdl { namespace DlSystem { +/** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * Definition of UDLFactoyFunc, using/typedef and default FactoryFunction + * UDLBundle - a simple way to bundle func and cookie into one type + */ + + +/** + * @brief . + * + * Convenient typedef for user defined layer creation factory + * + * @param[out] void* Cookie - a user opaque data that was passed during SNPE's runtime's + * CreateInstance. SNPE's runtime is passing this back to the user. + * + * @param[out] DlSystem::UDLContext* - The specific Layer Description context what is passe + * SNPE runtime. + * + * @return IUDL* - a Concrete instance of IUDL derivative + */ +using UDLFactoryFunc = std::function; + +/** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * default UDL factory implementation + * + * @param[out] DlSystem::UDLContext* - The specific Layer Description context what is passe + * SNPE runtime. + * + * @param[out] void* Cookie - a user opaque data that was passed during SNPE's runtime's + * CreateInstance. SNPE's runtime is passing this back to the user. + * + * @return IUDL* - nullptr to indicate SNPE's runtime that there is no specific + * implementation for UDL. When SNPE's runtime sees nullptr as a return + * value from the factory, it will halt execution if model has an unknown layer + * + */ +inline ZDL_EXPORT zdl::DlSystem::IUDL* DefaultUDLFunc(void*, const zdl::DlSystem::UDLContext*) { return nullptr; } + +/** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. + * + * @brief . + * + * Simple struct to bundle 2 elements. + * A user defined cookie that would be returned for each + * IUDL call. The user can place anything there and the + * SNPE runtime will provide it back + */ +struct ZDL_EXPORT UDLBundle { + void *cookie = nullptr; + UDLFactoryFunc func = DefaultUDLFunc; +}; + +}} + + +#endif // _UDL_FUNC_HPP_ diff --git a/third_party/snpe/include/DlSystem/UserBufferMap.hpp b/third_party/snpe/include/DlSystem/UserBufferMap.hpp new file mode 100644 index 0000000000..a03ddfe1d1 --- /dev/null +++ b/third_party/snpe/include/DlSystem/UserBufferMap.hpp @@ -0,0 +1,122 @@ +//============================================================================= +// +// Copyright (c) 2017 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include "ZdlExportDefine.hpp" +#include "StringList.hpp" + +#ifndef DL_SYSTEM_USER_BUFFER_MAP_HPP +#define DL_SYSTEM_USER_BUFFER_MAP_HPP + +namespace DlSystem +{ + // Forward declaration of UserBuffer map implementation. + class UserBufferMapImpl; +} + +namespace zdl +{ +namespace DlSystem +{ +class IUserBuffer; + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing the map of UserBuffer. + */ +class ZDL_EXPORT UserBufferMap final +{ +public: + + /** + * @brief . + * + * Creates a new empty UserBuffer map + */ + UserBufferMap(); + + /** + * copy constructor. + * @param[in] other object to copy. + */ + UserBufferMap(const UserBufferMap& other); + + /** + * assignment operator. + */ + UserBufferMap& operator=(const UserBufferMap& other); + + /** + * @brief Adds a name and the corresponding UserBuffer pointer + * to the map + * + * @param[in] name The name of the UserBuffer + * @param[in] userBuffer The pointer to the UserBuffer + * + * @note If a UserBuffer with the same name already exists, the new + * UserBuffer pointer would be updated. + */ + void add(const char *name, zdl::DlSystem::IUserBuffer *buffer); + + /** + * @brief Removes a mapping of one UserBuffer and its name by its name + * + * @param[in] name The name of UserBuffer to be removed + * + * @note If no UserBuffer with the specified name is found, nothing + * is done. + */ + void remove(const char *name) noexcept; + + /** + * @brief Returns the number of UserBuffers in the map + */ + size_t size() const noexcept; + + /** + * @brief . + * + * Removes all UserBuffers from the map + */ + void clear() noexcept; + + /** + * @brief Returns the UserBuffer given its name. + * + * @param[in] name The name of the UserBuffer to get. + * + * @return nullptr if no UserBuffer with the specified name is + * found; otherwise, a valid pointer to the UserBuffer. + */ + zdl::DlSystem::IUserBuffer* getUserBuffer(const char *name) const noexcept; + + /** + * @brief . + * + * Returns the names of all UserBuffers + * + * @return A list of UserBuffer names. + */ + zdl::DlSystem::StringList getUserBufferNames() const; + + ~UserBufferMap(); +private: + void swap(const UserBufferMap &other); + std::unique_ptr<::DlSystem::UserBufferMapImpl> m_UserBufferMapImpl; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // DlSystem namespace +} // zdl namespace + + +#endif // DL_SYSTEM_TENSOR_MAP_HPP + diff --git a/third_party/snpe/include/DlSystem/UserMemoryMap.hpp b/third_party/snpe/include/DlSystem/UserMemoryMap.hpp new file mode 100644 index 0000000000..3685a8ddab --- /dev/null +++ b/third_party/snpe/include/DlSystem/UserMemoryMap.hpp @@ -0,0 +1,129 @@ +//============================================================================= +// +// Copyright (c) 2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= +#include +#include "ZdlExportDefine.hpp" +#include "StringList.hpp" + +#ifndef DL_SYSTEM_USER_MEMORY_MAP_HPP +#define DL_SYSTEM_USER_MEMORY_MAP_HPP + +namespace DlSystem +{ + // Forward declaration of UserMemory map implementation. + class UserMemoryMapImpl; +} + +namespace zdl +{ +namespace DlSystem +{ +class IUserBuffer; + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing the map of UserMemory. + */ +class ZDL_EXPORT UserMemoryMap final +{ +public: + + /** + * @brief . + * + * Creates a new empty UserMemory map + */ + UserMemoryMap(); + + /** + * copy constructor. + * @param[in] other object to copy. + */ + UserMemoryMap(const UserMemoryMap& other); + + /** + * assignment operator. + */ + UserMemoryMap& operator=(const UserMemoryMap& other); + + /** + * @brief Adds a name and the corresponding buffer address + * to the map + * + * @param[in] name The name of the UserMemory + * @param[in] address The pointer to the Buffer Memory + * + * @note If a UserBuffer with the same name already exists, the new + * address would be updated. + */ + void add(const char *name, void *address); + + /** + * @brief Removes a mapping of one Buffer address and its name by its name + * + * @param[in] name The name of Memory address to be removed + * + * @note If no UserBuffer with the specified name is found, nothing + * is done. + */ + void remove(const char *name) noexcept; + + /** + * @brief Returns the number of User Memory addresses in the map + */ + size_t size() const noexcept; + + /** + * @brief . + * + * Removes all User Memory from the map + */ + void clear() noexcept; + + /** + * @brief . + * + * Returns the names of all User Memory + * + * @return A list of Buffer names. + */ + zdl::DlSystem::StringList getUserBufferNames() const; + + /** + * @brief Returns the no of UserMemory addresses mapped to the buffer + * + * @param[in] name The name of the UserMemory + * + */ + size_t getUserMemoryAddressCount(const char *name) const noexcept; + + /** + * @brief Returns address at a specified index corresponding to a UserMemory buffer name + * + * @param[in] name The name of the buffer + * @param[in] index The index in the list of addresses + * + */ + void* getUserMemoryAddressAtIndex(const char *name, uint32_t index) const noexcept; + + ~UserMemoryMap(); +private: + void swap(const UserMemoryMap &other); + std::unique_ptr<::DlSystem::UserMemoryMapImpl> m_UserMemoryMapImpl; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // DlSystem namespace +} // zdl namespace + + +#endif // DL_SYSTEM_TENSOR_MAP_HPP + diff --git a/third_party/snpe/include/DlSystem/ZdlExportDefine.hpp b/third_party/snpe/include/DlSystem/ZdlExportDefine.hpp new file mode 100644 index 0000000000..92eb786d31 --- /dev/null +++ b/third_party/snpe/include/DlSystem/ZdlExportDefine.hpp @@ -0,0 +1,13 @@ +//============================================================================= +// +// Copyright (c) 2015, 2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================= + +#pragma once + +#ifndef ZDL_EXPORT +#define ZDL_EXPORT +#endif diff --git a/third_party/snpe/include/PlatformValidator/PlatformValidator.hpp b/third_party/snpe/include/PlatformValidator/PlatformValidator.hpp new file mode 100644 index 0000000000..66097ba569 --- /dev/null +++ b/third_party/snpe/include/PlatformValidator/PlatformValidator.hpp @@ -0,0 +1,118 @@ +// ============================================================================= +// +// Copyright (c) 2018-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +// ============================================================================= + +#ifndef SNPE_PLATFORMVALIDATOR_HPP +#define SNPE_PLATFORMVALIDATOR_HPP + +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +#define DO_PRAGMA(s) _Pragma(#s) +#define NO_WARNING "-Wunused-variable" + +#ifdef __clang__ +#define SNPE_DISABLE_WARNINGS(clang_warning,gcc_warning) \ +_Pragma("clang diagnostic push") \ +DO_PRAGMA(clang diagnostic ignored clang_warning) + +#define SNPE_ENABLE_WARNINGS \ +_Pragma("clang diagnostic pop") + +#elif defined __GNUC__ +#define SNPE_DISABLE_WARNINGS(clang_warning,gcc_warning) \ +_Pragma("GCC diagnostic push") \ +DO_PRAGMA(GCC diagnostic ignored gcc_warning) + +#define SNPE_ENABLE_WARNINGS \ +_Pragma("GCC diagnostic pop") + +#else +#define SNPE_DISABLE_WARNINGS(...) +#define SNPE_ENABLE_WARNINGS +#endif + +SNPE_DISABLE_WARNINGS("-Wdelete-non-virtual-dtor","-Wdelete-non-virtual-dtor") +#include +#include +SNPE_ENABLE_WARNINGS + +namespace zdl +{ + namespace SNPE + { + class PlatformValidator; + + class IPlatformValidatorRuntime; + } +} + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** +* The class for checking SNPE compatibility/capability of a device. +* +*/ + +class ZDL_EXPORT zdl::SNPE::PlatformValidator +{ +public: + /** + * @brief Default Constructor of the PlatformValidator Class + * + * @return A new instance of a PlatformValidator object + * that can be used to check the SNPE compatibility + * of a device + */ + PlatformValidator(); + + ~PlatformValidator(); + + /** + * @brief Sets the runtime processor for compatibility check + * + * @return Void + */ + void setRuntime(zdl::DlSystem::Runtime_t runtime); + + /** + * @brief Checks if the Runtime prerequisites for SNPE are available. + * + * @return True if the Runtime prerequisites are available, else false. + */ + bool isRuntimeAvailable(); + + /** + * @brief Returns the core version for the Runtime selected. + * + * @return String which contains the actual core version value + */ + std::string getCoreVersion(); + + /** + * @brief Returns the library version for the Runtime selected. + * + * @return String which contains the actual lib version value + */ + std::string getLibVersion(); + + /** + * @brief Runs a small program on the runtime and Checks if SNPE is supported for Runtime. + * + * @return If True, the device is ready for SNPE execution, else not. + */ + + bool runtimeCheck(); + +private: + zdl::DlSystem::Runtime_t m_runtimeType; + std::unique_ptr m_platformValidatorRuntime; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif //SNPE_PLATFORMVALIDATOR_HPP diff --git a/third_party/snpe/include/SNPE/ApplicationBufferMap.hpp b/third_party/snpe/include/SNPE/ApplicationBufferMap.hpp new file mode 100644 index 0000000000..380a3e0e6e --- /dev/null +++ b/third_party/snpe/include/SNPE/ApplicationBufferMap.hpp @@ -0,0 +1,101 @@ +//============================================================================== +// +// Copyright (c) 2019 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef PSNPE_APPLICATIONBUFFERMAP_HPP +#define PSNPE_APPLICATIONBUFFERMAP_HPP +#include +#include +#include + +#include "DlSystem/UserBufferMap.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl +{ +namespace PSNPE +{ +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * A class representing the UserBufferMap of Input and Output asynchronous mode. + */ + +class ZDL_EXPORT ApplicationBufferMap final +{ + + public: + /** + * @brief Adds a name and the corresponding buffer + * to the map + * + * @param[in] name The name of the UserBuffer + * @param[in] buffer The vector of the uint8_t data + * + * @note If a UserBuffer with the same name already exists, the new + * UserBuffer pointer would be updated. + */ + void add(const char* name, std::vector& buff) noexcept; + void add(const char* name, std::vector& buff) noexcept; + /** + * @brief Removes a mapping of one UserBuffer and its name by its name + * + * @param[in] name The name of UserBuffer to be removed + * + * @note If no UserBuffer with the specified name is found, nothing + * is done. + */ + void remove(const char* name) noexcept; + + /** + * @brief Returns the number of UserBuffers in the map + */ + size_t size() const noexcept; + + /** + * @brief . + * + * Removes all UserBuffers from the map + */ + void clear() noexcept; + + /** + * @brief Returns the UserBuffer given its name. + * + * @param[in] name The name of the UserBuffer to get. + * + * @return nullptr if no UserBuffer with the specified name is + * found; otherwise, a valid pointer to the UserBuffer. + */ + const std::vector& getUserBuffer(const char* name) const; + const std::vector& operator[](const char* name) const; + /** + * @brief . + * + * Returns the names of all UserAsyncBufferMap + * + * @return A list of UserBuffer names. + */ + zdl::DlSystem::StringList getUserBufferNames() const; + const std::unordered_map>& getUserBuffer() const; + explicit ApplicationBufferMap(); + ~ApplicationBufferMap(); + explicit ApplicationBufferMap( + const std::unordered_map> buffer); + + private: + std::unordered_map> m_UserMap; +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ +} // namespace PSNPE +} // namespace zdl + +#endif // PSNPE_APPLICATIONBUFFERMAP_HPP diff --git a/third_party/snpe/include/SNPE/PSNPE.hpp b/third_party/snpe/include/SNPE/PSNPE.hpp new file mode 100644 index 0000000000..a823c0c7fa --- /dev/null +++ b/third_party/snpe/include/SNPE/PSNPE.hpp @@ -0,0 +1,205 @@ +// ============================================================================= +// +// Copyright (c) 2019-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +// ============================================================================= + +#ifndef PSNPE_HPP +#define PSNPE_HPP + +#include +#include +#include "SNPE/SNPE.hpp" +#include "DlSystem/UserBufferMap.hpp" +#include "DlContainer/IDlContainer.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +#include "UserBufferList.hpp" +#include "RuntimeConfigList.hpp" +#include "ApplicationBufferMap.hpp" + +namespace zdl +{ +namespace PSNPE +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + *@ brief build snpe instance in serial or parallel + * + */ +enum ZDL_EXPORT BuildMode { + SERIAL = 0, + PARALLEL = 1 +}; +/** + * @brief Input and output transmission mode + */ +enum ZDL_EXPORT InputOutputTransmissionMode +{ + sync = 0, + outputAsync = 1, + inputOutputAsync = 2 +}; + +/** + * @brief A structure representing parameters of callback function of Async Output mode + */ +struct ZDL_EXPORT OutputAsyncCallbackParam +{ + size_t dataIndex; + bool executeStatus; + std::string errorMsg; + OutputAsyncCallbackParam(size_t _index,bool _status, const std::string& _errorMsg = std::string()) + : dataIndex(_index),executeStatus(_status), errorMsg(_errorMsg){}; +}; +/** + * @brief A structure representing parameters of callback function of Async Input/Output mode + */ +struct ZDL_EXPORT InputOutputAsyncCallbackParam +{ + size_t dataIndex; + const ApplicationBufferMap& outputMap; + bool executeStatus; + std::string errorMsg; + InputOutputAsyncCallbackParam(size_t _index, const ApplicationBufferMap& output_map,bool _status, + const std::string _ErrorMsg = std::string()) + : dataIndex(_index) + , outputMap(output_map) + , executeStatus(_status) + , errorMsg(_ErrorMsg){}; +}; +/** + * @brief This callback is called when the output data is ready, only use for Output Async mode + */ +using OutputAsyncCallbackFunc = std::function; +/** + * @brief This callback is called when the output data is ready, only use for Output-Input Async mode + */ +using InputOutputAsyncCallbackFunc = std::function; +/** + * @brief This callback is called when the input data is ready,only use for Output-Input Async mode + */ +using InputOutputAsyncInputCallback = std::function(const std::vector &, + const zdl::DlSystem::StringList &)>; +/** + * @brief . + * + * A structure PSNPE configuration + * + */ +struct ZDL_EXPORT BuildConfig final +{ + BuildMode buildMode = BuildMode::SERIAL; ///< Specify build in serial mode or parallel mode + zdl::DlContainer::IDlContainer* container;///< The opened container ptr + zdl::DlSystem::StringList outputBufferNames;///< Specify the output layer name + zdl::DlSystem::StringList outputTensors;///< Specify the output layer name + RuntimeConfigList runtimeConfigList;///< The runtime config list for PSNPE, @see RuntimeConfig + size_t inputThreadNumbers = 1;///< Specify the number of threads used in the execution phase to process input data, only used in inputOutputAsync mode + size_t outputThreadNumbers = 1;///< Specify the number of threads used in the execution phase to process output data, only used in inputOutputAsync and outputAsync mode + OutputAsyncCallbackFunc outputCallback;///< The callback to deal with output data ,only used in outputAsync mode + InputOutputAsyncCallbackFunc inputOutputCallback;///< The callback to deal with output data ,only used in inputOutputAsync mode + InputOutputAsyncInputCallback inputOutputInputCallback;///< The callback to deal with input data ,only used in inputOutputAsync mode + InputOutputTransmissionMode inputOutputTransmissionMode = InputOutputTransmissionMode::sync;///< Specify execution mode + zdl::DlSystem::ProfilingLevel_t profilingLevel = zdl::DlSystem::ProfilingLevel_t::OFF;///< Specify profiling level for Diaglog + uint64_t encode[2] = {0, 0}; + bool enableInitCache = false; + std::string platformOptions; + std::string diaglogOutputDir = "./diaglogs/"; ///< Specify a diaglog output directory to save the generated Diaglog files. +}; +/** + * @brief . + * + * The class for executing SNPE instances in parallel. + */ +class ZDL_EXPORT PSNPE final +{ + public: + ~PSNPE(); + + explicit PSNPE() noexcept :m_TransmissionMode(InputOutputTransmissionMode::sync){}; + + /** + * @brief Build snpe instances. + * + */ + bool build(BuildConfig& buildConfig) noexcept; + + /** + * @brief Execute snpe instances in Async Output mode and Sync mode + * + * @param[in] inputBufferList A list of user buffers that contains the input data + * + * @param[in,out] outputBufferList A list of user buffers that will hold the output data + * + */ + bool execute(UserBufferList& inputBufferList, UserBufferList& outputBufferList) noexcept; + + /** + * @brief Execute snpe instances in Async Input/Output mode + * + * @param[in]inputMap A map of input buffers that contains input data. The names of buffers + * need to be matched with names retrived through getInputTensorNames() + * + * @param dataIndex Index of the input data + * + * @param isTF8buff Whether prefer to using 8 bit quantized element for inference + * + * @return True if executed successfully; flase, otherwise. + */ + bool executeInputOutputAsync(const std::vector& inputMap, size_t dataIndex, bool isTF8buff) noexcept; + bool executeInputOutputAsync(const std::vector& inputMap, size_t dataIndex, bool isTF8buff,bool isTF8Outputbuff) noexcept; + /** + * @brief Returns the input layer names of the network. + * + * @return StringList which contains the input layer names + */ + const zdl::DlSystem::StringList getInputTensorNames() const noexcept; + + /** + * @brief Returns the output layer names of the network. + * + * @return StringList which contains the output layer names + */ + const zdl::DlSystem::StringList getOutputTensorNames() const noexcept; + + /** + * @brief Returns the input tensor dimensions of the network. + * + * @return TensorShape which contains the dimensions. + */ + const zdl::DlSystem::TensorShape getInputDimensions() const noexcept; + + const zdl::DlSystem::TensorShape getInputDimensions(const char *name) const noexcept; + + /** + * @brief Returns attributes of buffers. + * + * @see zdl::SNPE + * + * @return BufferAttributes of input/output tensor named. + */ + const zdl::DlSystem::TensorShape getBufferAttributesDims(const char *name) const noexcept; + + zdl::DlSystem::Optional getInputOutputBufferAttributes(const char *name) const noexcept; + bool registerIonBuffers(const zdl::DlSystem::UserMemoryMap& ionBufferMap) const noexcept; + bool deregisterIonBuffers(const zdl::DlSystem::StringList& ionBufferNames) const noexcept; + + const char* getLastErrorString(); + + private: + PSNPE(const PSNPE&) = delete; + PSNPE& operator=(const PSNPE&) = delete; + zdl::PSNPE::InputOutputTransmissionMode m_TransmissionMode; + +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ +} // namespace PSNPE +} // namespace zdl +#endif // PSNPE_HPP diff --git a/third_party/snpe/include/SNPE/RuntimeConfigList.hpp b/third_party/snpe/include/SNPE/RuntimeConfigList.hpp new file mode 100644 index 0000000000..837dba092a --- /dev/null +++ b/third_party/snpe/include/SNPE/RuntimeConfigList.hpp @@ -0,0 +1,85 @@ +//============================================================================== +// +// Copyright (c) 2019-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== +#ifndef PSNPE_RUNTIMECONFIGLIST_HPP +#define PSNPE_RUNTIMECONFIGLIST_HPP + +#include +#include "DlContainer/IDlContainer.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/RuntimeList.hpp" +#include "DlSystem/TensorShapeMap.hpp" +#include "DlSystem/ZdlExportDefine.hpp" +namespace zdl { +namespace PSNPE { + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * The structure for configuring a BulkSNPE runtime + * + */ +struct ZDL_EXPORT RuntimeConfig final { + zdl::DlSystem::Runtime_t runtime; + zdl::DlSystem::RuntimeList runtimeList; + zdl::DlSystem::PerformanceProfile_t perfProfile; + zdl::DlSystem::TensorShapeMap inputDimensionsMap; + bool enableCPUFallback; + RuntimeConfig() + : runtime{zdl::DlSystem::Runtime_t::CPU_FLOAT32}, + perfProfile{zdl::DlSystem::PerformanceProfile_t::HIGH_PERFORMANCE}, + enableCPUFallback{false} {} + RuntimeConfig(const RuntimeConfig& other) { + runtime = other.runtime; + runtimeList = other.runtimeList; + perfProfile = other.perfProfile; + enableCPUFallback = other.enableCPUFallback; + inputDimensionsMap = other.inputDimensionsMap; + } + + RuntimeConfig& operator=(const RuntimeConfig& other) { + this->runtimeList = other.runtimeList; + this->runtime = other.runtime; + this->perfProfile = other.perfProfile; + this->enableCPUFallback = other.enableCPUFallback; + this->inputDimensionsMap = other.inputDimensionsMap; + return *this; + } + + ~RuntimeConfig() {} +}; + +/** + * @brief . + * + * The class for creating a RuntimeConfig container. + * + */ +class ZDL_EXPORT RuntimeConfigList final { + public: + RuntimeConfigList(); + RuntimeConfigList(const size_t size); + void push_back(const RuntimeConfig& runtimeConfig); + RuntimeConfig& operator[](const size_t index); + RuntimeConfigList& operator=(const RuntimeConfigList& other); + size_t size() const noexcept; + size_t capacity() const noexcept; + void clear() noexcept; + ~RuntimeConfigList() = default; + + private: + void swap(const RuntimeConfigList& other); + std::vector m_runtimeConfigs; +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // namespace PSNPE +} // namespace zdl +#endif // PSNPE_RUNTIMECONFIGLIST_HPP diff --git a/third_party/snpe/include/SNPE/SNPE.hpp b/third_party/snpe/include/SNPE/SNPE.hpp new file mode 100644 index 0000000000..5ab45b82ee --- /dev/null +++ b/third_party/snpe/include/SNPE/SNPE.hpp @@ -0,0 +1,258 @@ +//============================================================================== +// +// Copyright (c) 2015-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _SNPE_SNPE_HPP_ +#define _SNPE_SNPE_HPP_ + +#include "DlSystem/DlOptional.hpp" +#include "DlSystem/DlVersion.hpp" +#include "DlSystem/IBufferAttributes.hpp" +#include "DlSystem/ITensor.hpp" +#include "DlSystem/TensorShape.hpp" +#include "DlSystem/TensorMap.hpp" +#include "DlSystem/String.hpp" +#include "DlSystem/StringList.hpp" +#include "DlSystem/IUserBuffer.hpp" +#include "DlSystem/UserBufferMap.hpp" +#include "DlSystem/UserMemoryMap.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl { + namespace SNPE + { + class SnpeRuntime; + } +} +namespace zdl { + namespace DiagLog + { + class IDiagLog; + } +} + +namespace zdl { namespace SNPE { +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief . + * + * The SNPE interface class definition + */ +class ZDL_EXPORT SNPE final +{ +public: + + // keep this undocumented to be hidden in doxygen using HIDE_UNDOC_MEMBERS + explicit SNPE(std::unique_ptr&& runtime) noexcept; + ~SNPE(); + + /** + * @brief Gets the names of input tensors to the network + * + * To support multiple input scenarios, where multiple tensors are + * passed through execute() in a TensorMap, each tensor needs to + * be uniquely named. The names of tensors can be retrieved + * through this function. + * + * In the case of a single input, one name will be returned. + * + * @note Note that because the returned value is an Optional list, + * the list must be verified as boolean true value before being + * dereferenced. + * + * @return An Optional List of input tensor names. + * + * @see zdl::DlSystem::Optional + */ + zdl::DlSystem::Optional + getInputTensorNames() const noexcept; + + /** + * @brief Gets the names of output tensors to the network + * + * @return List of output tensor names. + */ + zdl::DlSystem::Optional + getOutputTensorNames() const noexcept; + + /** + * @brief Gets the name of output tensor from the input layer name + * + * @return Output tensor name. + */ + zdl::DlSystem::StringList + getOutputTensorNamesByLayerName(const char *name) const noexcept; + + /** + * @brief Processes the input data and returns the output + * + * @param[in] A map of tensors that contains the input data for + * each input. The names of tensors needs to be + * matched with names retrieved through + * getInputTensorNames() + * + * @param[in,out] An empty map of tensors that will contain the output + * data of potentially multiple layers (the key + * in the map is the layer name) upon return + * + * @note output tensormap has to be empty. To forward propagate + * and get results in user-supplied tensors, use + * executeWithSuppliedOutputTensors. + */ + bool execute(const zdl::DlSystem::TensorMap &input, + zdl::DlSystem::TensorMap &output) noexcept; + + /** + * @brief Processes the input data and returns the output + * + * @param[in] A single tensor contains the input data. + * + * @param[in,out] An empty map of tensors that will contain the output + * data of potentially multiple layers (the key + * in the map is the layer name) upon return + * + * @note output tensormap has to be empty. + */ + bool execute(const zdl::DlSystem::ITensor *input, + zdl::DlSystem::TensorMap &output) noexcept; + + /** + * @brief Processes the input data and returns the output, using + * user-supplied buffers + * + * @param[in] A map of UserBuffers that contains the input data for + * each input. The names of UserBuffers needs to be + * matched with names retrieved through + * getInputTensorNames() + * + * @param[in,out] A map of UserBuffers that will hold the output + * data of potentially multiple layers (the key + * in the map is the UserBuffer name) + * + * @note input and output UserBuffer maps must be fully pre-populated. with + * dimensions matching what the network expects. + * For example, if there are 5 output UserBuffers they all have to be + * present in map. + * + * Caller must guarantee that for the duration of execute(), the buffer + * stored in UserBuffer would remain valid. For more detail on buffer + * ownership and lifetime requirements, please refer to zdl::DlSystem::UserBuffer + * documentation. + */ + bool execute(const zdl::DlSystem::UserBufferMap &input, + const zdl::DlSystem::UserBufferMap &output) noexcept; + + + /** + * @brief Regiter Client ION Buffers + * @param[in] A UserMemoryMap of virtual addresses + * + */ + bool registerIonBuffers(const zdl::DlSystem::UserMemoryMap& ionBufferMap) noexcept; + + /** + * @brief Regiter Client ION Buffers + * @param[in] A StringList of ION Buffer names + * + */ + bool deregisterIonBuffers(const zdl::DlSystem::StringList& ionBufferNames) noexcept; + + /** + * @brief Returns the version string embedded at model conversion + * time. + * + * @return Model version string, which is a free-form string + * supplied at the time of the conversion + * + */ + zdl::DlSystem::String getModelVersion() const noexcept; + + /** + * @brief Returns the dimensions of the input data to the model in the + * form of TensorShape. The dimensions in TensorShape corresponds to + * what the tensor dimensions would need to be for an input tensor to + * the model. + * + * @param[in] layer input name. + * + * @note Note that this function only makes sense for networks + * that have a fixed input size. For networks in which the + * input size varies with each call of Execute(), this + * function should not be used. + * + * @note Because the returned type is an Optional instance, it must + * be verified as a boolean true value before being dereferenced. + * + * @return An Optional instance of TensorShape that maintains dimensions, + * matching the tensor dimensions for input to the model, + * where the last entry is the fastest varying dimension, etc. + * + * @see zdl::DlSystem::ITensor + * @see zdl::DlSystem::TensorShape + * @see zdl::DlSystem::Optional + */ + zdl::DlSystem::Optional + getInputDimensions() const noexcept; + zdl::DlSystem::Optional + getInputDimensions(const char *name) const noexcept; + + /** + * @brief Gets the output layer(s) for the network. + * + * Note that the output layers returned by this function may be + * different than those specified when the network was created + * via the zdl::SNPE::SNPEBuilder. For example, if the + * network was created in debug mode with no explicit output + * layers specified, this will contain all layers. + * + * @note Note that because the returned value is an Optional StringList, + * the list must be verified as a boolean true value before being + * dereferenced. + * + * @return A List of output layer names. + * + * @see zdl::DlSystem::Optional + */ + zdl::DlSystem::Optional + getOutputLayerNames() const noexcept; + + /** + * @brief Returns attributes of buffers used to feed input tensors and receive result from output tensors. + * + * @param[in] Tensor name. + * + * @return BufferAttributes of input/output tensor named + */ + zdl::DlSystem::Optional getInputOutputBufferAttributes(const char *name) const noexcept; + + /** + * @brief . + * + * Get the diagnostic logging interface + * + * @note Note that because the returned type is an Optional instance, + * it must be verified as a boolean true value before being + * dereferenced. + * + * @see zdl::DlSystem::Optional + */ + zdl::DlSystem::Optional + getDiagLogInterface() noexcept; + +private: + SNPE(const SNPE&) = delete; + SNPE& operator=(const SNPE&) = delete; + + std::unique_ptr m_Runtime; +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ +}} + +#endif diff --git a/third_party/snpe/include/SNPE/SNPEBuilder.hpp b/third_party/snpe/include/SNPE/SNPEBuilder.hpp new file mode 100644 index 0000000000..5fc7846ced --- /dev/null +++ b/third_party/snpe/include/SNPE/SNPEBuilder.hpp @@ -0,0 +1,306 @@ +//============================================================================== +// +// Copyright (c) 2017-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _SNPE_BUILDER_HPP_ +#define _SNPE_BUILDER_HPP_ + +#include "SNPE/SNPE.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/UDLFunc.hpp" +#include "DlSystem/DlOptional.hpp" +#include "DlSystem/TensorShapeMap.hpp" +#include "DlSystem/PlatformConfig.hpp" +#include "DlSystem/IOBufferDataTypeMap.hpp" +#include "DlSystem/RuntimeList.hpp" + +namespace zdl { + namespace DlContainer + { + class IDlContainer; + } +} + +struct SNPEBuilderImpl; + + +namespace zdl { namespace SNPE { +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * The builder class for creating SNPE objects. + * Not meant to be extended. + */ +class ZDL_EXPORT SNPEBuilder final +{ +private: + std::unique_ptr<::SNPEBuilderImpl> m_Impl; +public: + + /** + * @brief Constructor of NeuralNetwork Builder with a supplied model. + * + * @param[in] container A container holding the model. + * + * @return A new instance of a SNPEBuilder object + * that can be used to configure and build + * an instance of SNPE. + * + */ + explicit SNPEBuilder( + zdl::DlContainer::IDlContainer* container); + ~SNPEBuilder(); + + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. Please use + * setRuntimeProcessorOrder() + * + * @brief Sets the runtime processor. + * + * @param[in] targetRuntimeProcessor The target runtime. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setRuntimeProcessor( + zdl::DlSystem::Runtime_t targetRuntimeProcessor); + + /** + * @brief Requests a performance profile. + * + * @param[in] targetRuntimeProfile The target performance profile. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setPerformanceProfile( + zdl::DlSystem::PerformanceProfile_t performanceProfile); + + /** + * @brief Sets the profiling level. Default profiling level for + * SNPEBuilder is off. Off and basic only applies to DSP runtime. + * + * @param[in] profilingLevel The target profiling level. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setProfilingLevel( + zdl::DlSystem::ProfilingLevel_t profilingLevel); + + /** + * @brief Sets a preference for execution priority. + * + * This allows the caller to give coarse hint to SNPE runtime + * about the priority of the network. SNPE runtime is free to use + * this information to co-ordinate between different workloads + * that may or may not extend beyond SNPE. + * + * @param[in] ExecutionPriorityHint_t The target performance profile. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setExecutionPriorityHint( + zdl::DlSystem::ExecutionPriorityHint_t priority); + + /** + * @brief Sets the layers that will generate output. + * + * @param[in] outputLayerNames List of layer names to + * output. An empty list will + * result in only the final + * layer of the model being + * the output layer. The list + * will be copied. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setOutputLayers( + const zdl::DlSystem::StringList& outputLayerNames); + + /** + * @brief Sets the output tensor names. + * + * @param[in] outputTensorNames List of tensor names to + * output. An empty list will + * result in producing output for the final + * output tensor of the model. + * The list will be copied. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setOutputTensors( + const zdl::DlSystem::StringList& outputTensorNames); + + /** + * @brief Passes in a User-defined layer. + * + * @param udlBundle Bundle of udl factory function and a cookie + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setUdlBundle( + zdl::DlSystem::UDLBundle udlBundle); + + /** + * @brief Sets whether this neural network will perform inference with + * input from user-supplied buffers, and write output to user-supplied + * buffers. Default behaviour is to use tensors created by + * ITensorFactory. + * + * @param[in] bufferMode Whether to use user-supplied buffer or not. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setUseUserSuppliedBuffers( + bool bufferMode); + + /** + * @brief Sets the debug mode of the runtime. + * + * @param[in] debugMode This enables debug mode for the runtime. It + * does two things. For an empty + * outputLayerNames list, all layers will be + * output. It might also disable some internal + * runtime optimizations (e.g., some networks + * might be optimized by combining layers, + * etc.). + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setDebugMode( + bool debugMode); + + /** + * NOTE: DEPRECATED, MAY BE REMOVED IN THE FUTURE. Please use + * setRuntimeProcessorOrder() + * + * @brief Sets the mode of CPU fallback functionality. + * + * @param[in] mode This flag enables/disables the functionality + * of CPU fallback. When the CPU fallback + * functionality is enabled, layers in model that + * violates runtime constraints will run on CPU + * while the rest of non-violating layers will + * run on the chosen runtime processor. In + * disabled mode, models with layers violating + * runtime constraints will NOT run on the chosen + * runtime processor and will result in runtime + * exception. By default, the functionality is + * enabled. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setCPUFallbackMode( + bool mode); + + + /** + * @brief Sets network's input dimensions to enable resizing of + * the spatial dimensions of each layer for fully convolutional networks, + * and the batch dimension for all networks. + * + * @param[in] tensorShapeMap The map of input names and their new dimensions. + * The new dimensions overwrite the input dimensions + * embedded in the model and then resize each layer + * of the model. If the model contains + * layers whose dimensions cannot be resized e.g FullyConnected, + * exception will be thrown when SNPE instance is actually built. + * In general the batch dimension is always resizable. + * After resizing of layers' dimensions in model based + * on new input dimensions, the new model is revalidated + * against all runtime constraints, whose failures may + * result in cpu fallback situation. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setInputDimensions(const zdl::DlSystem::TensorShapeMap& inputDimensionsMap); + + /** + * @brief Sets the mode of init caching functionality. + * + * @param[in] mode This flag enables/disables the functionality of init caching. + * When init caching functionality is enabled, a set of init caches + * will be created during network building/initialization process + * and will be added to DLC container. If such DLC container is saved + * by the user, in subsequent network building/initialization processes + * these init caches will be loaded from the DLC so as to reduce initialization time. + * In disable mode, no init caches will be added to DLC container. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setInitCacheMode( + bool cacheMode); + + /** + * @brief Returns an instance of SNPE based on the current parameters. + * + * @return A new instance of a SNPE object that can be used + * to execute models or null if any errors occur. + */ + std::unique_ptr build() noexcept; + + /** + * @brief Sets the platform configuration. + * + * @param[in] platformConfig The platform configuration. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setPlatformConfig(const zdl::DlSystem::PlatformConfig& platformConfig); + + /** + * @brief Sets network's runtime order of precedence. Example: + * CPU_FLOAT32, GPU_FLOAT16, AIP_FIXED8_TF + * Note:- setRuntimeProcessor() or setCPUFallbackMode() will be silently ignored when + * setRuntimeProcessorOrder() is invoked + * + * @param[in] runtimeList The list of runtime in order of precedence + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setRuntimeProcessorOrder(const zdl::DlSystem::RuntimeList& runtimeList); + + /** + * @brief Sets the unconsumed tensors as output + * + * @param[in] setOutput This enables unconsumed tensors (i.e) + * outputs which are not inputs to any + * layer (basically dead ends) to be marked + * for output + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setUnconsumedTensorsAsOutputs( + bool setOutput); + + /** + * @brief Execution terminated when exceeding time limit. + * Only valid for dsp runtime currently. + * + * @param[in] timeout Time limit value + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setTimeOut( + uint64_t timeout); + + + /** + * @brief Sets the datatype of the buffer. + * Only valid for dsp runtime currently. + * + * @param[in] Map of the buffer names and the datatype that needs to be set. + * + * @return The current instance of SNPEBuilder. + */ + SNPEBuilder& setBufferDataType(const zdl::DlSystem::IOBufferDataTypeMap& dataTypeMap); + +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +}} + +#endif diff --git a/third_party/snpe/include/SNPE/SNPEFactory.hpp b/third_party/snpe/include/SNPE/SNPEFactory.hpp new file mode 100644 index 0000000000..2d78e81b17 --- /dev/null +++ b/third_party/snpe/include/SNPE/SNPEFactory.hpp @@ -0,0 +1,220 @@ +//============================================================================== +// +// Copyright (c) 2015-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef _SNPE_FACTORY_HPP_ +#define _SNPE_FACTORY_HPP_ + +#include "SNPE/SNPE.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/UDLFunc.hpp" +#include "DlSystem/ZdlExportDefine.hpp" +#include "DlSystem/DlOptional.hpp" + +namespace zdl { + namespace DlSystem + { + class ITensorFactory; + class IUserBufferFactory; + } + namespace DlContainer + { + class IDlContainer; + } +} + + + +namespace zdl { namespace SNPE { +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * The factory class for creating SNPE objects. + * + */ +class ZDL_EXPORT SNPEFactory +{ +public: + + /** + * Indicates whether the supplied runtime is available on the + * current platform. + * + * @param[in] runtime The target runtime to check. + * + * @return True if the supplied runtime is available; false, + * otherwise. + */ + static bool isRuntimeAvailable(zdl::DlSystem::Runtime_t runtime); + + /** + * Indicates whether the supplied runtime is available on the + * current platform. + * + * @param[in] runtime The target runtime to check. + * + * @param[in] option Extent to perform runtime available check. + * + * @return True if the supplied runtime is available; false, + * otherwise. + */ + static bool isRuntimeAvailable(zdl::DlSystem::Runtime_t runtime, + zdl::DlSystem::RuntimeCheckOption_t option); + + /** + * Gets a reference to the tensor factory. + * + * @return A reference to the tensor factory. + */ + static zdl::DlSystem::ITensorFactory& getTensorFactory(); + + /** + * Gets a reference to the UserBuffer factory. + * + * @return A reference to the UserBuffer factory. + */ + static zdl::DlSystem::IUserBufferFactory& getUserBufferFactory(); + + /** + * Gets the version of the SNPE library. + * + * @return Version of the SNPE library. + * + */ + static zdl::DlSystem::Version_t getLibraryVersion(); + + /** + * Set the SNPE storage location for all SNPE instances in this + * process. Note that this may only be called once, and if so + * must be called before creating any SNPE instances. + * + * @param[in] storagePath Absolute path to a directory which SNPE may + * use for caching and other storage purposes. + * + * @return True if the supplied path was succesfully set as + * the SNPE storage location, false otherwise. + */ + static bool setSNPEStorageLocation(const char* storagePath); + + /** + * @brief Register a user-defined op package with SNPE. + * + * @param[in] regLibraryPath Path to the registration library + * that allows clients to register a set of operations that are + * part of the package, and share op info with SNPE + * + * @return True if successful, False otherwise. + */ + static bool addOpPackage( const std::string& regLibraryPath ); + + /** + * Indicates whether the OpenGL and OpenCL interoperability is supported + * on GPU platform. + * + * @return True if the OpenGL and OpenCl interop is supported; false, + * otherwise. + */ + static bool isGLCLInteropSupported(); + + static const char* getLastError(); + + /** + * Initializes logging with the specified log level. + * initializeLogging with level, is used on Android platforms + * and after successful initialization, SNPE + * logs are printed in android logcat logs. + * + * It is recommended to initializeLogging before creating any + * SNPE instances, in order to capture information related to + * core initialization. If this is called again after first + * time initialization, subsequent calls are ignored. + * Also, Logging can be re-initialized after a call to + * terminateLogging API by calling initializeLogging again. + * + * A typical usage of Logging life cycle can be + * initializeLogging() + * any other SNPE API like isRuntimeAvailable() + * * setLogLevel() - optional - can be called anytime + * between initializeLogging & terminateLogging + * SNPE instance creation, inference, destroy + * terminateLogging(). + * + * Please note, enabling logging can have performance impact. + * + * @param[in] LogLevel_t Log level (LOG_INFO, LOG_WARN, etc.). + * + * @return True if successful, False otherwise. + */ + static bool initializeLogging(const zdl::DlSystem::LogLevel_t& level); + + /** + * Initializes logging with the specified log level and log path. + * initializeLogging with level & log path, is used on non Android + * platforms and after successful initialization, SNPE + * logs are printed in std output & into log files created in the + * log path. + * + * It is recommended to initializeLogging before creating any + * SNPE instances, in order to capture information related to + * core initialization. If this is called again after first + * time initialization, subsequent calls are ignored. + * Also, Logging can be re-initialized after a call to + * terminateLogging API by calling initializeLogging again. + * + * A typical usage of Logging life cycle can be + * initializeLogging() + * any other SNPE API like isRuntimeAvailable() + * * setLogLevel() - optional - can be called anytime + * between initializeLogging & terminateLogging + * SNPE instance creation, inference, destroy + * terminateLogging() + * + * Please note, enabling logging can have performance impact + * + * @param[in] LogLevel_t Log level (LOG_INFO, LOG_WARN, etc.). + * + * @param[in] Path of directory to store logs. + * If path is empty, the default path is "./Log". + * For android, the log path is ignored. + * + * @return True if successful, False otherwise. + */ + static bool initializeLogging(const zdl::DlSystem::LogLevel_t& level, const std::string& logPath); + + /** + * Updates the current logging level with the specified level. + * setLogLevel is optional, called anytime after initializeLogging + * and before terminateLogging, to update the log level set. + * Log levels can be updated multiple times by calling setLogLevel + * A call to setLogLevel() is ignored if it is made before + * initializeLogging() or after terminateLogging() + * + * @param[in] LogLevel_t Log level (LOG_INFO, LOG_WARN, etc.). + * + * @return True if successful, False otherwise. + */ + static bool setLogLevel(const zdl::DlSystem::LogLevel_t& level); + + /** + * Terminates logging. + * + * It is recommended to terminateLogging after initializeLogging + * in order to disable logging information. + * If this is called before initialization or after first time termination, + * calls are ignored. + * + * @return True if successful, False otherwise. + */ + static bool terminateLogging(void); +}; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ +}} + + +#endif diff --git a/third_party/snpe/include/SNPE/UserBufferList.hpp b/third_party/snpe/include/SNPE/UserBufferList.hpp new file mode 100644 index 0000000000..a660bca0f6 --- /dev/null +++ b/third_party/snpe/include/SNPE/UserBufferList.hpp @@ -0,0 +1,49 @@ +//============================================================================== +// +// Copyright (c) 2019 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== +#ifndef PSNPE_USERBUFFERLIST_HPP +#define PSNPE_USERBUFFERLIST_HPP + +#include +#include "DlSystem/UserBufferMap.hpp" +#include "DlSystem/ZdlExportDefine.hpp" + +namespace zdl { +namespace PSNPE +{ + +/** @addtogroup c_plus_plus_apis C++ +@{ */ +/** +* @brief . +* +* The class for creating a UserBufferMap container. +* +*/ +class ZDL_EXPORT UserBufferList final +{ +public: + UserBufferList(); + UserBufferList(const size_t size); + void push_back(const zdl::DlSystem::UserBufferMap &userBufferMap); + zdl::DlSystem::UserBufferMap& operator[](const size_t index); + UserBufferList& operator =(const UserBufferList &other); + size_t size() const noexcept; + size_t capacity() const noexcept; + void clear() noexcept; + ~UserBufferList() = default; + +private: + void swap(const UserBufferList &other); + std::vector m_userBufferMaps; + +}; +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +} // namespace PSNPE +} // namespace zdl +#endif //PSNPE_USERBUFFERLIST_HPP diff --git a/third_party/snpe/include/SnpeUdo/UdoBase.h b/third_party/snpe/include/SnpeUdo/UdoBase.h new file mode 100644 index 0000000000..7b2567920e --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoBase.h @@ -0,0 +1,537 @@ +//============================================================================== +// +// Copyright (c) 2019-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef SNPE_UDO_BASE_H +#define SNPE_UDO_BASE_H + +#include + +// Provide values to use for API version. +#define API_VERSION_MAJOR 1 +#define API_VERSION_MINOR 6 +#define API_VERSION_TEENY 0 + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +// Defines a bitmask of enum values. +typedef uint32_t SnpeUdo_Bitmask_t; +typedef SnpeUdo_Bitmask_t Udo_Bitmask_t; + +// A string of characters, rather than an array of bytes. +// Assumed to be UTF-8. +typedef char* SnpeUdo_String_t; +typedef SnpeUdo_String_t Udo_String_t; + +// The maximum allowable length of a SnpeUdo_String_t in bytes, +// including null terminator. SNPE will truncate strings longer +// than this. +#define SNPE_UDO_MAX_STRING_SIZE 1024 + +/** + * An enum which holds the various error types. + * The error types are divided to classes : + * 0 - 99 : generic errors + * 100 - 200 : errors related to configuration + * + */ +typedef enum +{ + /// No Error + SNPE_UDO_NO_ERROR = 0, UDO_NO_ERROR = 0, + /// Unsupported value for core type + SNPE_UDO_WRONG_CORE = 1, UDO_WRONG_CORE = 1, + /// Invalid attribute/argument passed into UDO API + SNPE_UDO_INVALID_ARGUMENT = 2, UDO_INVALID_ARGUMENT = 2, + /// Unsupported feature error + SNPE_UDO_UNSUPPORTED_FEATURE = 3, UDO_UNSUPPORTED_FEATURE = 3, + /// Error relating to memory allocation + SNPE_UDO_MEM_ALLOC_ERROR = 4, UDO_MEM_ALLOC_ERROR = 4, + /* Configuration Specific errors */ + /// No op with given attributes available in library + SNPE_UDO_WRONG_OPERATION = 100, UDO_WRONG_OPERATION = 100, + /// Unsupported value for core type in UDO configuration + SNPE_UDO_WRONG_CORE_TYPE = 101, UDO_WRONG_CORE_TYPE = 101, + /// Wrong number of params in UDO definition + SNPE_UDO_WRONG_NUM_OF_PARAMS = 102, UDO_WRONG_NUM_OF_PARAMS = 102, + /// Wrong number of dimensions for tensor(s) in UDO definition + SNPE_UDO_WRONG_NUM_OF_DIMENSIONS = 103, UDO_WRONG_NUM_OF_DIMENSIONS = 103, + /// Wrong number of input tensors in UDO definition + SNPE_UDO_WRONG_NUM_OF_INPUTS = 104, UDO_WRONG_NUM_OF_INPUTS = 104, + /// Wrong number of output tensors in UDO definition + SNPE_UDO_WRONG_NUM_OF_OUTPUTS = 105, UDO_WRONG_NUM_OF_OUTPUTS = 105, + SNPE_UDO_PROGRAM_CACHE_NOT_FOUND = 106, UDO_PROGRAM_CACHE_NOT_FOUND = 106, + SNPE_UDO_UNKNOWN_ERROR = 0xFFFFFFFF, UDO_UNKNOWN_ERROR = 0xFFFFFFFF +} SnpeUdo_ErrorType_t; + +typedef SnpeUdo_ErrorType_t Udo_ErrorType_t; + +/** + * An enum which holds the various data types. + * Designed to be used as single values or combined into a bitfield parameter + * (0x1, 0x2, 0x4, etc) + * \n FIXED_XX types are targeted for data in tensors. + * \n UINT / INT types are targeted for scalar params + */ +typedef enum +{ + /// data type: 16-bit floating point + SNPE_UDO_DATATYPE_FLOAT_16 = 0x01, UDO_DATATYPE_FLOAT_16 = 0x01, + /// data type: 32-bit floating point + SNPE_UDO_DATATYPE_FLOAT_32 = 0x02, UDO_DATATYPE_FLOAT_32 = 0x02, + /// data type: 4-bit fixed point + SNPE_UDO_DATATYPE_FIXED_4 = 0x04, UDO_DATATYPE_FIXED_4 = 0x04, + /// data type: 8-bit fixed point + SNPE_UDO_DATATYPE_FIXED_8 = 0x08, UDO_DATATYPE_FIXED_8 = 0x08, + /// data type: 16-bit fixed point + SNPE_UDO_DATATYPE_FIXED_16 = 0x10, UDO_DATATYPE_FIXED_16 = 0x10, + /// data type: 32-bit fixed point + SNPE_UDO_DATATYPE_FIXED_32 = 0x20, UDO_DATATYPE_FIXED_32 = 0x20, + /// data type: 8-bit unsigned integer + SNPE_UDO_DATATYPE_UINT_8 = 0x100, UDO_DATATYPE_UINT_8 = 0x100, + /// data type: 16-bit unsigned integer + SNPE_UDO_DATATYPE_UINT_16 = 0x200, UDO_DATATYPE_UINT_16 = 0x200, + /// data type: 32-bit unsigned integer + SNPE_UDO_DATATYPE_UINT_32 = 0x400, UDO_DATATYPE_UINT_32 = 0x400, + /// data type: 8-bit signed integer + SNPE_UDO_DATATYPE_INT_8 = 0x1000, UDO_DATATYPE_INT_8 = 0x1000, + /// data type: 16-bit signed integer + SNPE_UDO_DATATYPE_INT_16 = 0x2000, UDO_DATATYPE_INT_16 = 0x2000, + /// data type: 32-bit signed integer + SNPE_UDO_DATATYPE_INT_32 = 0x4000, UDO_DATATYPE_INT_32 = 0x4000, + SNPE_UDO_DATATYPE_LAST = 0xFFFFFFFF, UDO_DATATYPE_LAST = 0xFFFFFFFF +} SnpeUdo_DataType_t; + +typedef SnpeUdo_DataType_t Udo_DataType_t; + +/** + * An enum which holds the various layouts. + * Designed to be used as single values or combined into a bitfield parameter + * (0x1, 0x2, 0x4, etc) + */ +typedef enum +{ + /// data layout (4D): NHWC (batch-height-width-channel) + SNPE_UDO_LAYOUT_NHWC = 0x01, UDO_LAYOUT_NHWC = 0x01, + /// data layout (4D): NCHW (batch-channel-height-width) + SNPE_UDO_LAYOUT_NCHW = 0x02, UDO_LAYOUT_NCHW = 0x02, + /// data layout (5D): NDHWC (batch-dimension-height-width-channel) + SNPE_UDO_LAYOUT_NDHWC = 0x04, UDO_LAYOUT_NDHWC = 0x04, + SNPE_UDO_LAYOUT_GPU_OPTIMAL1 = 0x08, UDO_LAYOUT_GPU_OPTIMAL1 = 0x08, + SNPE_UDO_LAYOUT_GPU_OPTIMAL2 = 0x10, UDO_LAYOUT_GPU_OPTIMAL2 = 0x10, + SNPE_UDO_LAYOUT_DSP_OPTIMAL1 = 0x11, UDO_LAYOUT_DSP_OPTIMAL1 = 0x11, + SNPE_UDO_LAYOUT_DSP_OPTIMAL2 = 0x12, UDO_LAYOUT_DSP_OPTIMAL2 = 0x12, + // Indicates no data will be allocated for this tensor. + // Used to specify optional inputs/outputs positionally. + SNPE_UDO_LAYOUT_NULL = 0x13, UDO_LAYOUT_NULL = 0x13, + SNPE_UDO_LAYOUT_LAST = 0xFFFFFFFF, UDO_LAYOUT_LAST = 0xFFFFFFFF +} SnpeUdo_TensorLayout_t; + +typedef SnpeUdo_TensorLayout_t Udo_TensorLayout_t; + +/** + * An enum which holds the UDO library Core type . + * Designed to be used as single values or combined into a bitfield parameter + * (0x1, 0x2, 0x4, etc) + */ +typedef enum +{ + /// Library target IP Core is undefined + SNPE_UDO_CORETYPE_UNDEFINED = 0x00, UDO_CORETYPE_UNDEFINED = 0x00, + /// Library target IP Core is CPU + SNPE_UDO_CORETYPE_CPU = 0x01, UDO_CORETYPE_CPU = 0x01, + /// Library target IP Core is GPU + SNPE_UDO_CORETYPE_GPU = 0x02, UDO_CORETYPE_GPU = 0x02, + /// Library target IP Core is DSP + SNPE_UDO_CORETYPE_DSP = 0x04, UDO_CORETYPE_DSP = 0x04, + SNPE_UDO_CORETYPE_LAST = 0xFFFFFFFF, UDO_CORETYPE_LAST = 0xFFFFFFFF +} SnpeUdo_CoreType_t; + +typedef SnpeUdo_CoreType_t Udo_CoreType_t; + +/** + * An enum to specify the parameter type : Scalar or Tensor + */ +typedef enum +{ + /// UDO static param type: scalar + SNPE_UDO_PARAMTYPE_SCALAR = 0x00, UDO_PARAMTYPE_SCALAR = 0x00, + /// UDO static param type: string + SNPE_UDO_PARAMTYPE_STRING = 0x01, UDO_PARAMTYPE_STRING = 0x01, + /// UDO static param type: tensor + SNPE_UDO_PARAMTYPE_TENSOR = 0x02, UDO_PARAMTYPE_TENSOR = 0x02, + SNPE_UDO_PARAMTYPE_LAST = 0xFFFFFFFF, UDO_PARAMTYPE_LAST = 0xFFFFFFFF +} SnpeUdo_ParamType_t; + +typedef SnpeUdo_ParamType_t Udo_ParamType_t; + +/** + * An enum to specify quantization type + */ +typedef enum +{ + /// Tensor Quantization type: NONE. Signifies unquantized tensor data + SNPE_UDO_QUANTIZATION_NONE = 0x00, UDO_QUANTIZATION_NONE = 0x00, + /// Tensor Quantization type: Tensorflow-style + SNPE_UDO_QUANTIZATION_TF = 0x01, UDO_QUANTIZATION_TF = 0x01, + SNPE_UDO_QUANTIZATION_QMN = 0x02, UDO_QUANTIZATION_QMN = 0x02, + SNPE_UDO_QUANTIZATION_LAST = 0xFFFFFFFF, UDO_QUANTIZATION_LAST = 0xFFFFFFFF +} SnpeUdo_QuantizationType_t; + +typedef SnpeUdo_QuantizationType_t Udo_QuantizationType_t; + +/** + * @brief A struct which is used to provide a version number using 3 values : major, minor, teeny + * + */ +typedef struct +{ + /// version field: major - for backward-incompatible changes + uint32_t major; + /// version field: minor - for backward-compatible feature updates + uint32_t minor; + /// version field: teeny - for minor bug-fixes and clean-up + uint32_t teeny; +} SnpeUdo_Version_t; + +typedef SnpeUdo_Version_t Udo_Version_t; + +/** + * @brief A struct returned from version query, contains the Library version and API version + * + */ +typedef struct +{ + /// Version of UDO library. Controlled by users + SnpeUdo_Version_t libVersion; + /// Version of SNPE UDO API used in compiling library. Determined by SNPE + SnpeUdo_Version_t apiVersion; +} SnpeUdo_LibVersion_t; + +/** + * @brief A struct returned from version query, contains the package version + * + */ +typedef struct +{ + /// Version of UDO API used in package. + Udo_Version_t apiVersion; +} Udo_PkgVersion_t; + +/** + * @brief A union to hold the value of a generic type. Allows defining a parameter struct + * in a generic way, with a "value" location that holds the data regardless of the type. + * + */ +typedef union +{ + /// value type: float + float floatValue; + /// value type: unsigned 32-bit integer + uint32_t uint32Value; + /// value type: signed 32-bit integer + int32_t int32Value; + /// value type: unsigned 16-bit integer + uint16_t uint16Value; + /// value type: signed 16-bit integer + int16_t int16Value; + /// value type: unsigned 8-bit integer + uint8_t uint8Value; + /// value type: signed 8-bit integer + int8_t int8Value; +} SnpeUdo_Value_t; + +typedef SnpeUdo_Value_t Udo_Value_t; + +/** + * @brief A struct which defines a scalar parameter : name, data type, and union of values + * + */ +typedef struct +{ + /// The parameter data type : float, int, etc. + SnpeUdo_DataType_t dataType; + /// a union of specified type which holds the data + SnpeUdo_Value_t dataValue; +} SnpeUdo_ScalarParam_t; + +typedef SnpeUdo_ScalarParam_t Udo_ScalarParam_t; + +/** + * @brief A struct which defines the quantization parameters in case of Tensorflow style quantization + * + */ +typedef struct +{ + /// minimum value of the quantization range of data + float minValue; + /// maximum value of the quantization range of data + float maxValue; +} SnpeUdo_TFQuantize_t; + +typedef SnpeUdo_TFQuantize_t Udo_TFQuantize_t; + +/** + * @brief A struct which defines the quantization type, and union of supported quantization structs + * + */ +typedef struct +{ + /// quantization type (only TF-style currently supported) + SnpeUdo_QuantizationType_t quantizeType; + union + { + /// TF-style min-max quantization ranges + SnpeUdo_TFQuantize_t TFParams; + }; +} SnpeUdo_QuantizeParams_t; + +typedef SnpeUdo_QuantizeParams_t Udo_QuantizeParams_t; + +/** + * @brief A struct which defines the datatype associated with a specified core-type + * This should be used to denote the datatypes for a single tensor info, depending + * on the intended execution core. + * + */ +typedef struct +{ + /// The IP Core + SnpeUdo_CoreType_t coreType; + /// The associated datatype for this coreType + SnpeUdo_DataType_t dataType; +} SnpeUdo_PerCoreDatatype_t; + +typedef SnpeUdo_PerCoreDatatype_t Udo_PerCoreDatatype_t; + +/** + * @brief A struct which defines a tensor parameter : name, data type, layout, quantization, more. + * Also holds a pointer to the tensor data. + * + */ +typedef struct +{ + /// The maximum allowable dimensions of the tensor. The memory held in + /// _tensorData_ is guaranteed to be large enough for this. + uint32_t* maxDimensions; + /// The current dimensions of the tensor. An operation may modify the current + /// dimensions of its output, to indicate cases where the output has been + /// "resized". + /// Note that for static parameters, the current and max dimensions must + /// match. + uint32_t* currDimensions; + /// Quantization params applicable to the tensor. Currently only supports + /// Tensorflow quantization style. + SnpeUdo_QuantizeParams_t quantizeParams; + /// Number of dimensions to the tensor: 3D, 4D, etc. + uint32_t tensorRank; + /// The parameter data type: float, int, etc. + SnpeUdo_DataType_t dataType; + /// The tensor layout type: NCHW, NHWC, etc. + SnpeUdo_TensorLayout_t layout; + /// Opaque pointer to tensor data. User may be required to re-interpret the pointer + /// based on core-specific definitions. + void* tensorData; +} SnpeUdo_TensorParam_t; + +typedef SnpeUdo_TensorParam_t Udo_TensorParam_t; + +/** + * @brief A struct which defines tensor information for activation tensors only + * + * It describes an activation tensor object using its name, the intended layout and the datatype + * it will take depending on the intended runtime core. The repeated field indicates that + * that the tensor info describes several input/output activation tensors, which all share the + * aforementioned properties. + */ +typedef struct +{ + /// The tensor name + SnpeUdo_String_t tensorName; + /// The tensor layout type: NCHW, NHWC, etc. + SnpeUdo_TensorLayout_t layout; + /// The per core datatype: {SNPE_UDO_DATATYPE, SNPE_UDO_CORE_TYPE} + SnpeUdo_PerCoreDatatype_t* perCoreDatatype; + /// A boolean field indicating that this tensorinfo will be repeated e.x for ops such as Concat or Split + bool repeated; + /// A boolean field indicating whether input is static or not. + bool isStatic; +} SnpeUdo_TensorInfo_t; + +typedef SnpeUdo_TensorInfo_t Udo_TensorInfo_t; + +/** + * @brief struct which defines a UDO parameter - a union of scalar, tensor and string parameters + * + */ +typedef struct +{ + /// Type is scalar or tensor + SnpeUdo_ParamType_t paramType; + /// The param name, for example : "offset", "activation_type" + SnpeUdo_String_t paramName; + union + { + /// scalar param value + SnpeUdo_ScalarParam_t scalarParam; + /// tensor param value + SnpeUdo_TensorParam_t tensorParam; + /// string param value + SnpeUdo_String_t stringParam; + }; +} SnpeUdo_Param_t; + +typedef SnpeUdo_Param_t Udo_Param_t; + +/** + * @brief A struct which defines Operation information which is specific for IP core (CPU, GPU, DSP ...) + * + */ +typedef struct +{ + /// The IP Core + SnpeUdo_CoreType_t udoCoreType; + /// Bitmask, defines supported internal calculation types (like FLOAT_32, etc) + /// Based on SnpeUdo_DataType + SnpeUdo_Bitmask_t operationCalculationTypes; +} SnpeUdo_OpCoreInfo_t; + +typedef SnpeUdo_OpCoreInfo_t Udo_OpCoreInfo_t; + +/** + * @brief A struct which defines the common and core-specific Operation information + * + */ +typedef struct +{ + /// Operation type + SnpeUdo_String_t operationType; + /// A bitmask describing which IP Cores (CPU, GPU, DSP ...) support this operation + /// Translated based on SnpeUdo_CoreType + SnpeUdo_Bitmask_t supportedByCores; + /// Number of static parameters defined by the op + uint32_t numOfStaticParams; + /// Array of static parameters. Can be scalar or tensor params + SnpeUdo_Param_t* staticParams; + /// Number of input tensors this op receives + uint32_t numOfInputs; + /// Array of input tensor names to this operation + SnpeUdo_String_t* inputNames; + /// Number of output tensors this op receives + uint32_t numOfOutputs; + /// Array of output tensor names to this operation + SnpeUdo_String_t* outputNames; + /// Number of cores that the op can execute on + uint32_t numOfCoreInfo; + /// Array of per-core information entries + SnpeUdo_OpCoreInfo_t* opPerCoreInfo; + /// Array of input tensor infos for this operation + SnpeUdo_TensorInfo_t* inputInfos; + /// Array of output tensor infos for this operation + SnpeUdo_TensorInfo_t* outputInfos; +} SnpeUdo_OperationInfo_t; + +typedef SnpeUdo_OperationInfo_t Udo_OperationInfo_t; + +/** + * @brief A struct which provides the implementation library info : type, name + * + */ +typedef struct +{ + /// Defines the IP Core that this implementation library is targeting + SnpeUdo_CoreType_t udoCoreType; + /// library name. will be looked at in the standard library path + SnpeUdo_String_t libraryName; +} SnpeUdo_LibraryInfo_t; + +typedef SnpeUdo_LibraryInfo_t Udo_LibraryInfo_t; + +/** + * @brief A struct returned by the registration library and contains information on the UDO package : + * name, operations, libraries, etc. + * + */ +typedef struct +{ + /// A string containing the package name + SnpeUdo_String_t packageName; + /// A bitmask describing supported IP cores (CPU, GPU, DSP ...) + /// Translated based on SnpeUdo_CoreType + SnpeUdo_Bitmask_t supportedCoreTypes; + /// The number of implementation libraries in the package + uint32_t numOfImplementationLib; + /// Array of implementation libraries names/types + SnpeUdo_LibraryInfo_t* implementationLib; + /// A string containing all operation types separated by space + SnpeUdo_String_t operationsString; + /// Number of supported operations + uint32_t numOfOperations; + /// Array of Operation info structs. Each entry describes one + /// Operation (name, params, inputs, outputs) + SnpeUdo_OperationInfo_t* operationsInfo; +} SnpeUdo_RegInfo_t; + +typedef SnpeUdo_RegInfo_t Udo_RegInfo_t; + +/** +* @brief A struct returned by the implementation library and contains information on the +* specific library: name, IP Core, operations, etc. +* +*/ +typedef struct +{ + /// Defines the IP Core that this implementation library is targeting + SnpeUdo_CoreType_t udoCoreType; + /// A string containing the package name + SnpeUdo_String_t packageName; + /// A string containing all operation types separated by space + SnpeUdo_String_t operationsString; + /// Number of supported operations + uint32_t numOfOperations; +} SnpeUdo_ImpInfo_t; + +typedef SnpeUdo_ImpInfo_t Udo_ImpInfo_t; + +/** + * @brief This struct defines an operation. It is used for validation + * or creation of an operation. + * In case of using it for creation, the static params which are tensors + * contain pointers to the real data (weights, for example), and input/output + * tensors also include pointers to the buffers used. + */ +typedef struct +{ + /// The IP Core that the operation is defined for - CPU, GPU, DSP... + SnpeUdo_CoreType_t udoCoreType; + /// Operation type + SnpeUdo_String_t operationType; + /// The number of static parameters provided in the staticParams array. + /// this number has to match the number provided by the UDO Registration library information + uint32_t numOfStaticParams; + /// Array of static parameters + SnpeUdo_Param_t* staticParams; + /// The number of input parameters provided in inputs array. + /// this number has to match the number provided by the UDO Registration library information + uint32_t numOfInputs; + /// Array of input tensors, providing layout, data type, sizes, etc + /// When used to create an operation, also contains the initial location of the data + SnpeUdo_TensorParam_t* inputs; + /// The number of output parameters provided in inputs array. + /// this number has to match the number provided by the UDO Registration library information + uint32_t numOfOutputs; + /// Array of output tensors, providing layout, data type, sizes, etc + /// When used to create an operation, also contains the initial location of the data + SnpeUdo_TensorParam_t* outputs; +} SnpeUdo_OpDefinition_t; + +typedef SnpeUdo_OpDefinition_t Udo_OpDefinition_t; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif //SNPE_UDO_BASE_H diff --git a/third_party/snpe/include/SnpeUdo/UdoImpl.h b/third_party/snpe/include/SnpeUdo/UdoImpl.h new file mode 100644 index 0000000000..a0cb648cf7 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoImpl.h @@ -0,0 +1,343 @@ +//============================================================================== +// +// Copyright (c) 2019-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef SNPE_UDO_IMPL_H +#define SNPE_UDO_IMPL_H + +#include + +#include "SnpeUdo/UdoShared.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +typedef struct _SnpeUdo_OpFactory_t* SnpeUdo_OpFactory_t; +typedef struct _SnpeUdo_Operation_t* SnpeUdo_Operation_t; + +typedef SnpeUdo_OpFactory_t Udo_OpFactory_t; +typedef SnpeUdo_Operation_t Udo_Operation_t; + +/** + * @brief Initialize the shared library's data structures. Calling any other + * library function before this one will result in error. + * + * @param[in] globalInfrastructure Global core-specific infrastructure to be + * used by operations created in this library. The definition and + * semantics of this object will be defined in the corresponding + * implementation header for the core type. + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_initImplLibrary(void* globalInfrastructure); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_InitImplLibraryFunction_t)(void*); + +/** + * @brief A function to query the API version of the UDO implementation library. + * The function populates a SnpeUdo_LibVersion_t struct, which contains a SnpeUdo_Version_t + * struct for API version and library version. + * + * @param[in, out] version A pointer to struct which contains major, minor, teeny information for + * library and api versions. + * + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_getImplVersion(SnpeUdo_LibVersion_t** version); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_getImplVersion_t)(SnpeUdo_LibVersion_t** version); + +/** + * @brief Release the shared library's data structures, and invalidate any + * handles returned by the library. The behavior of any outstanding + * asynchronous calls made to this library when this function is called + * are undefined. All library functions (except SnpeUdo_initImplLibrary) will + * return an error after this function has been successfully called. + * + * It should be possible to call SnpeUdo_initImplLibrary after calling this + * function, and re-initialize the library. + * + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_terminateImplLibrary(void); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_TerminateImplLibraryFunction_t)(void); + + +/** + * @brief A function to query info on the UDO implementation library. + * The function populates a structure which contains information about + * operations that are part of this library + * + * @param[in, out] implementationInfo A pointer to struct which contains information + * on the operations + * + * @return error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_getImpInfo(SnpeUdo_ImpInfo_t** implementationInfo); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_GetImpInfoFunction_t)(SnpeUdo_ImpInfo_t** implementationInfo); + +typedef SnpeUdo_GetImpInfoFunction_t Udo_GetImpInfoFunction_t; + +/** + * @brief A function to create an operation factory. + * The function receives the operation type, and an array of static parameters, + * and returns operation factory handler + * + * @param[in] udoCoreType The Core type to create the operation on. An error will + * be returned if this does not match the core type of the library. + * + * @param[in] perFactoryInfrastructure CreateOpFactory infrastructure appropriate to this + * core type. The definition and semantics of this object will be defined + * in the corresponding implementation header for the core type. + * + * @param[in] operationType A string containing Operation type. for example "MY_CONV" + * + * @param[in] numOfStaticParams The number of static parameters. + * + * @param[in] staticParams Array of static parameters + * + * @param[in,out] opFactory Handler to Operation Factory, to be used when creating operations + * + * @return Error Code + */ +SnpeUdo_ErrorType_t +SnpeUdo_createOpFactory(SnpeUdo_CoreType_t udoCoreType, + void* perFactoryInfrastructure, + SnpeUdo_String_t operationType, + uint32_t numOfStaticParams, + SnpeUdo_Param_t* staticParams, + SnpeUdo_OpFactory_t* opFactory); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_CreateOpFactoryFunction_t)(SnpeUdo_CoreType_t, + void*, + SnpeUdo_String_t, + uint32_t, + SnpeUdo_Param_t*, + SnpeUdo_OpFactory_t*); + +typedef SnpeUdo_CreateOpFactoryFunction_t Udo_CreateOpFactoryFunction_t; + +/** + * @brief A function to release the resources allocated for an operation factory + * created by this library. + * + * @param[in] factory The operation factory to release. Upon success this handle will be invalidated. + * + * @return Error Code + */ +SnpeUdo_ErrorType_t +SnpeUdo_releaseOpFactory(SnpeUdo_OpFactory_t opFactory); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ReleaseOpFactoryFunction_t)(SnpeUdo_OpFactory_t); + +typedef SnpeUdo_ReleaseOpFactoryFunction_t Udo_ReleaseOpFactoryFunction_t; + +/** + * @brief A function to create an operation from the factory. + * The function receives array of inputs and array of outputs, and creates an operation + * instance, returning the operation instance handler. + * + * @param[in] opFactory OpFactory instance containing the parameters for this operation. + * + * @param[in] perOpInfrastructure Per-Op infrastructure for this operation. The definition + * and semantics of this object will be defined in the implementation header + * appropriate to this core type. + * + * @param[in] numOfInputs The number of input tensors this operation will receive. + * + * @param[in] inputs Array of input tensors, providing both the sizes and initial + * location of the data. + * + * @param[in] numOfOutputs Number of output tensors this operation will produce. + * + * @param[in] outputs Array of output tensors, providing both the sizes and + * initial location of the data. + * + * @param[in,out] operation Handle for newly created operation instance. + * + * @return Error Code + */ +SnpeUdo_ErrorType_t +SnpeUdo_createOperation(SnpeUdo_OpFactory_t opFactory, + void* perOpInfrastructure, + uint32_t numOfInputs, + SnpeUdo_TensorParam_t* inputs, + uint32_t numOfOutputs, + SnpeUdo_TensorParam_t* outputs, + SnpeUdo_Operation_t* operation); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_CreateOperationFunction_t)(SnpeUdo_OpFactory_t, + void*, + uint32_t, + SnpeUdo_TensorParam_t*, + uint32_t, + SnpeUdo_TensorParam_t*, + SnpeUdo_Operation_t*); + +typedef SnpeUdo_CreateOperationFunction_t Udo_CreateOperationFunction_t; + +/** + * @brief A pointer to notification function. + * + * The notification function supports the non-blocking (e.g. asynchronous) execution use-case. + * In case an "executeUdoOp" function is called with "blocking" set to zero, and a + * notify function, this function will be called by the implementation library at the + * end of execution. The implementation library will pass the notify function the ID + * that was provided to it when "executeUdoOp" was called. + * + * @param[in] ID 32-bit value, that was provided to executeUdoOp by the calling entity. + * Can be used to track the notifications, in case of multiple execute calls issued. + * + * @return Error code + * + */ +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ExternalNotify_t)(const uint32_t ID); + +typedef SnpeUdo_ExternalNotify_t Udo_ExternalNotify_t; + +/** + * @brief Operation execution function. + * + * Calling this function will run the operation on set of inputs, generating a set of outputs. + * The call can be blocking (synchronous) or non-blocking (asynchronous). To support the + * non-blocking mode, the calling entity can pass an ID and a notification function. + * At the end of the execution this notification function would be called, passing it the ID. + * NOTE: Asynchronous execution mode not supported in this release. + * + * @param[in] operation handle to the operation on which execute is invoked + * @param[in] blocking flag to indicate execution mode. + * If set, execution is blocking, + * e.g SnpeUdo_executeOp call does not return until execution is done. + * If not set, SnpeUdo_executeOp returns immediately, and the + * library will call the notification function (if set) when execution is done. + * + * @param[in] ID 32-bit number that can be used by the calling entity to track execution + * in case of non-blocking execution. + * For example, it can be a sequence number, increased by one on each call. + * + * @param[in] notifyFunc Pointer to notification function. if the pointer is set, and execution is + * non-blocking, the library will call this function at end of execution, + * passing the number provided as ID + * + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_executeOp(SnpeUdo_Operation_t operation, + bool blocking, + const uint32_t ID, + SnpeUdo_ExternalNotify_t notifyFunc); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ExecuteOpFunction_t)(SnpeUdo_Operation_t, + bool, + const uint32_t, + SnpeUdo_ExternalNotify_t); + +typedef SnpeUdo_ExecuteOpFunction_t Udo_ExecuteOpFunction_t; + +/** + * @brief A function to setting the inputs & outputs. part of SnpeUdo_Operation struct, + * returned from creation of a new operation instance. + * Not supported in this release. + * + * This function allows the calling entity to change some of the inputs and outputs + * between calls to execute. + * Note that the change is limited to changing the pointer to the tensor data only. + * Any other change may be rejected by the implementation library, causing + * immediate invalidation of the operation instance + * + * @param[in] operation Operation on which IO tensors are set + * + * @param[in] inputs array of tensor parameters. The calling entity may provide a subset of the + * operation inputs, providing only those that it wants to change. + * + * @param[in] outputs array of tensor parameters. The calling entity may provide a subset of the + * operation outputs, providing only those that it wants to change. + * + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_setOpIO(SnpeUdo_Operation_t operation, + SnpeUdo_TensorParam_t* inputs, + SnpeUdo_TensorParam_t* outputs); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_SetOpIOFunction_t)(SnpeUdo_Operation_t, + SnpeUdo_TensorParam_t*, + SnpeUdo_TensorParam_t*); + +typedef SnpeUdo_SetOpIOFunction_t Udo_SetOpIOFunction_t; + +/** + * @brief A function to return execution times. + * + * This function can be called to query the operation execution times on the IP core + * on which the operation is run. The time is provided in micro-seconds + * + * @param[in] operation Handle to operation whose execution time is being profiled + * + * @param[in,out] executionTime pointer to a uint32 value.This function writes the operation + * execution time in usec into this value. + * + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_profileOp(SnpeUdo_Operation_t operation, uint32_t *executionTime); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ProfileOpFunction_t)(SnpeUdo_Operation_t, uint32_t*); + +typedef SnpeUdo_ProfileOpFunction_t Udo_ProfileOpFunction_t; + +/** + * @brief A function to release the operation instance + * \n When it is called, the implementation library needs to release all resources + * allocated for this operation instance. + * \n Note that all function pointers which are part of SnpeUdo_Operation become + * invalid once releaseUdoOp call returns. + * + * @param[in] operation Handle to operation to be released + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_releaseOp(SnpeUdo_Operation_t operation); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ReleaseOpFunction_t)(SnpeUdo_Operation_t); + +typedef SnpeUdo_ReleaseOpFunction_t Udo_ReleaseOpFunction_t; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //SNPE_UDO_IMPL_H diff --git a/third_party/snpe/include/SnpeUdo/UdoImplCpu.h b/third_party/snpe/include/SnpeUdo/UdoImplCpu.h new file mode 100644 index 0000000000..3bbe0638e6 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoImplCpu.h @@ -0,0 +1,44 @@ +//============================================================================== +// +// Copyright (c) 2019-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +// Header to be used by a CPU UDO Implementation library + +#ifndef SNPE_UDO_IMPL_CPU_H +#define SNPE_UDO_IMPL_CPU_H + +#include + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief This struct provides the infrastructure needed by a developer of + * CPU UDO Implementation library. + * + * The framework/runtime which loads the CPU UDO implementation library provides + * this infrastructure data to the loaded library at the time of op factory creation. + * as an opaque pointer. It contains hooks for the UDO library to invoke supported + * functionality at the time of execution + * + * @param getData function pointer to retrieve raw tensor data from opaque pointer + * passed into the UDO when creating an instance. + * @param getDataSize function pointer to retrieve tensor data size from opaque pointer + */ + +typedef struct +{ + /// function pointer to retrieve raw tensor data from opaque pointer + /// passed into the UDO when creating an instance. + float* (*getData)(void*); + /// function pointer to retrieve tensor data size from opaque pointer + size_t (*getDataSize) (void*); +} SnpeUdo_CpuInfrastructure_t; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // SNPE_UDO_IMPL_CPU_H \ No newline at end of file diff --git a/third_party/snpe/include/SnpeUdo/UdoImplDsp.h b/third_party/snpe/include/SnpeUdo/UdoImplDsp.h new file mode 100644 index 0000000000..b97a649320 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoImplDsp.h @@ -0,0 +1,207 @@ +//============================================================================== +// +// Copyright (c) 2019-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +//============================================================================== +/* + * THIS HEADER FILE IS COPIED FROM HEXAGON-NN PROJECT + * + */ +//============================================================================== + + +// Header to be used by a DSP Hexnn UDO Implementation library + +#ifndef SNPE_UDO_IMPL_DSP_H +#define SNPE_UDO_IMPL_DSP_H +#include +#include "SnpeUdo/UdoImpl.h" + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief A function to validate that a set of params is supported by an operation + * This function is HexNN specific, use case is when registration library is not in use. + * Optional function. + * + * @param[in] operationType Operation type + * @param[in] numOfStaticParams Number of static params defined by the op + * @param[in] staticParams Array of static params to the op + * @return Error code, indicating if the operation can be created on this set of configuration or not. + * + */ + +SnpeUdo_ErrorType_t +SnpeUdo_validateOperation (SnpeUdo_String_t operationType, + uint32_t numOfStaticParams, + const SnpeUdo_Param_t* staticParams); + +typedef SnpeUdo_ErrorType_t (*SnpeUdo_ValidateOperationFunction_t) (SnpeUdo_String_t, + uint32_t, + const SnpeUdo_Param_t*); + +typedef SnpeUdo_ValidateOperationFunction_t Udo_ValidateOperationFunction_t; + +// enum used for indicating input/outout tensor data layouts on DSP, plain vs d32 +typedef enum { + SNPE_UDO_DSP_TENSOR_LAYOUT_PLAIN = 0x00, UDO_DSP_TENSOR_LAYOUT_PLAIN = 0x00, + SNPE_UDO_DSP_TENSOR_LAYOUT_D32 = 0x01, UDO_DSP_TENSOR_LAYOUT_D32 = 0x01 +} SnpeUdo_HexNNTensorLayout_t; + +typedef SnpeUdo_HexNNTensorLayout_t Udo_HexNNTensorLayout_t; + +/** + * @brief A function to query numbers of inputs and outputs, + * quantization type of each input and each output as arrays, + * and data layout (plain vs d32) of each input and each output as arrays + * of an operation. + * inputsQuantTypes and inputsLayouts should point to arrays of size numOfInputs + * outputsQuantTypes and outputsLayouts should point to arrays of size numOfOutputs + * + * Note: inputsLayouts and inputsLayouts can point to NULL, in this case, it is + * assumed all inputs and/or outputs have plain data layouts, i.e. no D32 + * + * @param[in] operationType Operation type + * @param[in] numOfStaticParams Number of static params defined by the op + * @param[in] staticParams Array of static params to the op + * @param[in,out] numOfInputs Number of input tensors to the op + * @param[in,out] inputsQuantTypes Array of Quantization info for each input tensor + * @param[in,out] inputsLayouts Array of layout type for each input tensor + * @param[in,out] numOfOutputs Number of output tensors to the op + * @param[in,out] outputsQuantTypes Array of Quantization info for each output tensor + * @param[in,out] outputsLayouts Array of layout type for each output tensor + * @return error code, indicating status of query + */ + +SnpeUdo_ErrorType_t +SnpeUdo_queryOperation (SnpeUdo_String_t operationType, + uint32_t numOfStaticParams, + const SnpeUdo_Param_t* staticParams, + uint32_t* numOfInputs, + SnpeUdo_QuantizationType_t** inputsQuantTypes, + SnpeUdo_HexNNTensorLayout_t** inputsLayouts, + uint32_t* numOfOutputs, + SnpeUdo_QuantizationType_t** outputsQuantTypes, + SnpeUdo_HexNNTensorLayout_t** outputsLayouts); + +typedef SnpeUdo_ErrorType_t (*SnpeUdo_QueryOperationFunction_t) (SnpeUdo_String_t, + uint32_t, + const SnpeUdo_Param_t*, + uint32_t*, + SnpeUdo_QuantizationType_t**, + SnpeUdo_HexNNTensorLayout_t**, + uint32_t*, + SnpeUdo_QuantizationType_t**, + SnpeUdo_HexNNTensorLayout_t**); + +typedef SnpeUdo_QueryOperationFunction_t Udo_QueryOperationFunction_t; + +// Global infrastructure functions supported by Hexagon-NN v2 +typedef void (*workerThread_t) (void* perOpInfrastructure, void* userData); +typedef int (*udoSetOutputTensorSize_t) (void* perOpInfrastructure, uint32_t outIdx, uint32_t size); +typedef int (*udoGetInputD32Paddings_t) (void* perOpInfrastructure, uint32_t inIdx, + uint32_t* heightPadBefore, uint32_t* heightPadAfter, + uint32_t* widthPadBefore, uint32_t* widthPadAfter, + uint32_t* depthPadBefore, uint32_t* depthPadAfter); +typedef int (*udoSetOutputD32ShapeSizePaddings_t) (void* perOpInfrastructure, uint32_t outIdx, + uint32_t batch, + uint32_t height, uint32_t heightPadBefore, uint32_t heightPadAfter, + uint32_t width, uint32_t widthPadBefore, uint32_t widthPadAfter, + uint32_t depth, uint32_t depthPadBefore, uint32_t depthPadAfter, + SnpeUdo_DataType_t dataType); +typedef void* (*udoMemalign_t) (size_t n, size_t size); +typedef void* (*udoMalloc_t) (size_t size); +typedef void* (*udoCalloc_t) (size_t n, size_t size); +typedef void (*udoFree_t) (void* ptr); +typedef uint32_t (*udoGetVtcmSize_t) (void* perOpInfrastructure); +typedef void* (*udoGetVtcmPtr_t) (void* perOpInfrastructure); +typedef uint32_t (*udoVtcmIsReal_t) (void* perOpInfrastructure); +typedef void (*udoRunWorkerThreads_t) (void* perOpInfrastructure, uint32_t nThreads, workerThread_t w, void* userData); + +typedef struct hexNNv2GlobalInfra { + udoSetOutputTensorSize_t udoSetOutputTensorSize; + udoGetInputD32Paddings_t udoGetInputD32Paddings; + udoSetOutputD32ShapeSizePaddings_t udoSetOutputD32ShapeSizePaddings; + udoMemalign_t udoMemalign; + udoMalloc_t udoMalloc; + udoCalloc_t udoCalloc; + udoFree_t udoFree; + udoGetVtcmSize_t udoGetVtcmSize; + udoGetVtcmPtr_t udoGetVtcmPtr; + udoVtcmIsReal_t udoVtcmIsReal; + udoRunWorkerThreads_t udoRunWorkerThreads; +} SnpeUdo_HexNNv2GlobalInfra_t; + +typedef SnpeUdo_HexNNv2GlobalInfra_t Udo_HexNNv2GlobalInfra_t; + +// hexnn types +typedef enum hexnnInfraType { + UDO_INFRA_HEXNN_V2, + UDO_INFRA_HEXNN_V3 // reserved, do not use +} SnpeUdo_HexNNInfraType_t; + +typedef SnpeUdo_HexNNInfraType_t Udo_HexNNInfraType_t; + +typedef struct { + Udo_CreateOpFactoryFunction_t create_op_factory; + Udo_CreateOperationFunction_t create_operation; + Udo_ExecuteOpFunction_t execute_op; + Udo_ReleaseOpFunction_t release_op; + Udo_ReleaseOpFactoryFunction_t release_op_factory; + Udo_ValidateOperationFunction_t validate_op; + Udo_QueryOperationFunction_t query_op; +} udo_func_package_t; + +/** + * @brief Infrastructures needed by a developer of DSP Hexnn UDO Implementation library. + * + * The framework/runtime which loads the Hexnn UDO implementation library provides + * this infrastructure to the loaded library by calling "SnpeUdo_initImplLibrary" + * function, and passing it (cast to void*). The Hexnn UDO library is expected + * to cast it back to this structure. + * + */ +typedef struct dspGlobalInfrastructure { + SnpeUdo_Version_t dspInfraVersion; // api version + SnpeUdo_HexNNInfraType_t infraType; + SnpeUdo_HexNNv2GlobalInfra_t hexNNv2Infra; +} SnpeUdo_DspGlobalInfrastructure_t; + +typedef SnpeUdo_DspGlobalInfrastructure_t Udo_DspGlobalInfrastructure_t; + +/** + * hexnn v2 per op factory infrastructure + * + * The framework/runtime passes per op factory infrastructure as a void pointer + * to HexNN UDO implementation library by calling function "SnpeUdo_createOpFactory". + * UDO implementation library is expected to cast it back to this following struct. + * + */ +typedef struct hexnnv2OpFactoryInfra { + unsigned long graphId; +} SnpeUdo_HexNNv2OpFactoryInfra_t; + +typedef SnpeUdo_HexNNv2OpFactoryInfra_t Udo_HexNNv2OpFactoryInfra_t; + +/** + * hexnn v2 per operation infrastructure + * + * The framework/runtime passes per operation infrastructure as a void pointer + * to HexNN UDO implementation library by calling function "SnpeUdo_createOperation". + * UDO implementation library is expected to cast it to the following type and save it. + * + * This is needed to be passed back into some functions from global infrastructure. + * + */ +typedef void* SnpeUdo_HexNNv2OpInfra_t; + +typedef SnpeUdo_HexNNv2OpInfra_t Udo_HexNNv2OpInfra_t; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // SNPE_UDO_IMPL_DSP_H diff --git a/third_party/snpe/include/SnpeUdo/UdoImplGpu.h b/third_party/snpe/include/SnpeUdo/UdoImplGpu.h new file mode 100644 index 0000000000..1af654d110 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoImplGpu.h @@ -0,0 +1,112 @@ +//============================================================================== +// +// Copyright (c) 2019-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +// Header to be used by a GPU UDO Implementation library + +#ifndef SNPE_UDO_IMPL_GPU_H +#define SNPE_UDO_IMPL_GPU_H + +#include "CL/cl.h" +#include "SnpeUdo/UdoBase.h" + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * This header defines version 0.0.0 of the GPU UDO Infrastructure. + * It defines the interpretation of the global and per-OpFactory infrastructure pointers + * as well as the interpretation of tensorData pointers. + * + * The per-Operation infrastructure pointer is defined to be null, and should not be used. + * + * The SnpeUdoTensorParam_t struct below provides the interpretation for + * the tensorData opaque pointer for SnpeUdoTensorParams representing inputs or outputs. + * + * The tensorData opaque pointer populated in SnpeUdoScalarParam_t structs should be interpreted + * as a host-readable data pointer. + * + */ + +/** + * @brief Function to retrieve opencl program from Program Cache repository. + * @param programCache is opaque pointer to Program Cache repository provided by + * SNPE GPU UDO runtime. + * @param programName is name associated with opencl program for UDO. + * @param program is pointer to opencl program which will be populated with + * valid opencl program if found in Program Cache repository. + * @return SnpeUdo_ErrorType_t is error type returned. SNPE_UDO_NO_ERROR is returned + * on success. + */ +typedef SnpeUdo_ErrorType_t (*SnpeUdo_getProgram_t) + (void* programCache, const char* programName, cl_program* program); + +/** + * @brief Function to store valid opencl program in Program Cache repository. + * @param programCache is opaque pointer to Program Cache repository provided by + * SNPE GPU UDO runtime. + * @param programName is name associated with opencl program for UDO. + * @param program is valid opencl program after program is built. + * @return SnpeUdo_ErrorType_t is error type returned. SNPE_UDO_NO_ERROR is returned + * on success. + * */ +typedef SnpeUdo_ErrorType_t (*SnpeUdo_storeProgram_t) + (void* programCache, const char * programName, cl_program program); + +/** + * @brief Global Infrastructure Definition for GPU UDO Implementations. + */ +typedef struct { + // Infrastructure definition version. This header is 0.0.0 + SnpeUdo_Version_t gpuInfraVersion; + SnpeUdo_getProgram_t SnpeUdo_getProgram; + SnpeUdo_storeProgram_t SnpeUdo_storeProgram; +} SnpeUdo_GpuInfrastructure_t; + +/** + * @brief Per OpFactory Infrastructure Definition for GPU UDO Implementations. + * @note This version of the infrastructure definition guarantees that the same + * Per OpFactory infrastructure pointer will be provided to all OpFactories + * in the same network. + */ +typedef struct +{ + cl_context context; + cl_command_queue commandQueue; + void* programCache; +} SnpeUdo_GpuOpFactoryInfrastructure_t; + +/** + * @brief Opaque tensorData definition for operation inputs and outputs. + * + * The following is a list of all SnpeUdoTensorLayout_t values supported by the + * GPU UDO implementation, and how the parameters of the struct should be + * interpreted in each case: + * + * SNPE_UDO_LAYOUT_NHWC: + * mem shall be single-element array, pointing to a cl buffer memory object. + * the dimensions of this object match the dimensions specified in the encompassing + * SnpeUdoTensorParam_t's currDimensions. + * + * memCount shall be 1. + * + * paddedRank and paddedDimensions are undefined and shall be ignored by the UDO + * implementation. + * + */ +typedef struct +{ + cl_mem* mem; + uint32_t memCount; + uint32_t paddedRank; + uint32_t* paddedDimensions; + +} SnpeUdo_GpuTensorData_t; + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // SNPE_UDO_IMPL_GPU_H diff --git a/third_party/snpe/include/SnpeUdo/UdoReg.h b/third_party/snpe/include/SnpeUdo/UdoReg.h new file mode 100644 index 0000000000..a5d2398833 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoReg.h @@ -0,0 +1,108 @@ +//============================================================================== +// +// Copyright (c) 2019-2020 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef SNPE_UDO_REG_H +#define SNPE_UDO_REG_H + +#include "SnpeUdo/UdoShared.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief Initialize the shared library's data structures. Calling any other + * library function before this one will result in an error being returned. + * + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_initRegLibrary(void); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_InitRegLibraryFunction_t)(void); + +/** + * @brief A function to query the API version of the UDO registration library. + * The function populates a SnpeUdo_LibVersion_t struct, which contains a SnpeUdo_Version_t + * struct for API version and library version. + * + * @param[in, out] version A pointer to struct which contains major, minor, teeny information for + * library and api versions. + * + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_getRegLibraryVersion(SnpeUdo_LibVersion_t** version); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_getRegLibraryVersion_t)(SnpeUdo_LibVersion_t** version); + +/** + * @brief Release the shared library's data structures, and invalidate any + * handles returned by the library. The behavior of any outstanding + * asynchronous calls made to this library when this function is called + * are undefined. All library functions (except SnpeUdo_InitRegLibrary) will + * return an error after this function has been successfully called. + * + * It should be possible to call SnpeUdo_InitRegLibrary after calling this + * function, and re-initialize the library. + * + * @return Error code + */ +SnpeUdo_ErrorType_t +SnpeUdo_terminateRegLibrary(void); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_TerminateRegLibraryFunction_t)(void); + + +/** + * @brief A function to query the info on the UDO set. + * The function populates a structure which contains information about + * the package and operations contained in it. + * + * @param[in, out] registrationInfo A struct which contains information on the set of UDOs + * + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_getRegInfo(SnpeUdo_RegInfo_t** registrationInfo); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_GetRegInfoFunction_t)(SnpeUdo_RegInfo_t** registrationInfo); + +/** + * @brief A function to validate that a set of params is supported by an operation + * The function receives an operation definition struct, and returns if this configuration is + * supported (e.g. if an operation can be created using this configuration) + * + * @param[in] opDefinition A struct of SnpeUdo_OpDefinition type, containing the information needed to + * validate that an operation can be created with this configuration. + * + * @return Error code, indicating is the operation can be created on this set or not. + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_validateOperation(SnpeUdo_OpDefinition_t* opDefinition); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_ValidateOperationFunction_t)(SnpeUdo_OpDefinition_t* opDefinition); + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //SNPE_UDO_REG_H diff --git a/third_party/snpe/include/SnpeUdo/UdoShared.h b/third_party/snpe/include/SnpeUdo/UdoShared.h new file mode 100644 index 0000000000..418d9db9e2 --- /dev/null +++ b/third_party/snpe/include/SnpeUdo/UdoShared.h @@ -0,0 +1,48 @@ +//============================================================================== +// +// Copyright (c) 2019-2021 Qualcomm Technologies, Inc. +// All Rights Reserved. +// Confidential and Proprietary - Qualcomm Technologies, Inc. +// +//============================================================================== + +#ifndef SNPE_UDO_SHARED_H +#define SNPE_UDO_SHARED_H + +#include "SnpeUdo/UdoBase.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup c_plus_plus_apis C++ +@{ */ + +/** + * @brief A function to return the various versions as they relate to the UDO + * The function returns a struct containing the the following: + * libVersion: the version of the implementation library compiled for the UDO. Set by user + * apiVersion: the version of the UDO API used in compiling the implementation library. + * Set by SNPE + * + * @param[in, out] version A pointer to Version struct of type SnpeUdo_LibVersion_t + * + * @return Error code + * + */ +SnpeUdo_ErrorType_t +SnpeUdo_getVersion (SnpeUdo_LibVersion_t** version); + +typedef SnpeUdo_ErrorType_t +(*SnpeUdo_GetVersionFunction_t) (SnpeUdo_LibVersion_t** version); + +typedef SnpeUdo_GetVersionFunction_t Udo_GetVersionFunction_t; + +#ifdef __cplusplus +} // extern "C" +#endif + +/** @} */ /* end_addtogroup c_plus_plus_apis C++ */ + +#endif // SNPE_UDO_SHARED_H diff --git a/third_party/snpe/larch64 b/third_party/snpe/larch64 new file mode 120000 index 0000000000..2e2a1c315b --- /dev/null +++ b/third_party/snpe/larch64 @@ -0,0 +1 @@ +aarch64-ubuntu-gcc7.5 \ No newline at end of file diff --git a/third_party/snpe/x86_64 b/third_party/snpe/x86_64 new file mode 120000 index 0000000000..700025efab --- /dev/null +++ b/third_party/snpe/x86_64 @@ -0,0 +1 @@ +x86_64-linux-clang \ No newline at end of file diff --git a/third_party/snpe/x86_64-linux-clang/libHtpPrepare.so b/third_party/snpe/x86_64-linux-clang/libHtpPrepare.so new file mode 100644 index 0000000000..20d1377a01 --- /dev/null +++ b/third_party/snpe/x86_64-linux-clang/libHtpPrepare.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4c33680010a8c7b2eef33e809844c0ad1d5ab0f0ec37abd49d924204670b357 +size 13556072 diff --git a/third_party/snpe/x86_64-linux-clang/libSNPE.so b/third_party/snpe/x86_64-linux-clang/libSNPE.so new file mode 100644 index 0000000000..0367b1106b --- /dev/null +++ b/third_party/snpe/x86_64-linux-clang/libSNPE.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:024891d2e4e4e265a1e7e72b27bad41ee6ae077d2197f45959bb32f8071dc8cf +size 5350008 diff --git a/third_party/snpe/x86_64-linux-clang/libomp.so b/third_party/snpe/x86_64-linux-clang/libomp.so new file mode 100755 index 0000000000..db98cba162 --- /dev/null +++ b/third_party/snpe/x86_64-linux-clang/libomp.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4784aa68e7ebdbe97db732eab87618b0a5fb73abeab4daed5476e01829b0e6e +size 759208 diff --git a/tinygrad_repo b/tinygrad_repo index 2619a86d2a..480e5e7a12 160000 --- a/tinygrad_repo +++ b/tinygrad_repo @@ -1 +1 @@ -Subproject commit 2619a86d2a6157c12cc9b1773b4a03cf968a1309 +Subproject commit 480e5e7a1292bf2f84e18edffd06a985c4b48e65 diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index eb0af5b64a..2950a67ff2 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -248,7 +248,6 @@ std::tuple BinaryView::getSelection(QModelIndex index) { void BinaryViewModel::refresh() { beginResetModel(); - bit_flip_tracker = {}; items.clear(); if (auto dbc_msg = dbc()->msg(msg_id)) { row_count = dbc_msg->size; @@ -296,7 +295,7 @@ void BinaryViewModel::updateItem(int row, int col, uint8_t val, const QColor &co void BinaryViewModel::updateState() { const auto &last_msg = can->lastMessage(msg_id); const auto &binary = last_msg.dat; - // Handle size changes in binary data + // data size may changed. if (binary.size() > row_count) { beginInsertRows({}, row_count, binary.size() - 1); row_count = binary.size(); @@ -304,74 +303,26 @@ void BinaryViewModel::updateState() { endInsertRows(); } - auto &bit_flips = heatmap_live_mode ? last_msg.bit_flip_counts : getBitFlipChanges(binary.size()); - // Find the maximum bit flip count across the message - uint32_t max_bit_flip_count = 1; // Default to 1 to avoid division by zero - for (const auto &row : bit_flips) { - for (uint32_t count : row) { - max_bit_flip_count = std::max(max_bit_flip_count, count); - } - } - - const double max_alpha = 255.0; - const double min_alpha_with_signal = 25.0; // Base alpha for small flip counts - const double min_alpha_no_signal = 10.0; // Base alpha for small flip counts for no signal bits - const double log_factor = 1.0 + 0.2; // Factor for logarithmic scaling - const double log_scaler = max_alpha / log2(log_factor * max_bit_flip_count); - - for (size_t i = 0; i < binary.size(); ++i) { + const double max_f = 255.0; + const double factor = 0.25; + const double scaler = max_f / log2(1.0 + factor); + for (int i = 0; i < binary.size(); ++i) { for (int j = 0; j < 8; ++j) { auto &item = items[i * column_count + j]; - int bit_val = (binary[i] >> (7 - j)) & 1; - - double alpha = item.sigs.empty() ? 0 : min_alpha_with_signal; - uint32_t flip_count = bit_flips[i][j]; - if (flip_count > 0) { - double normalized_alpha = log2(1.0 + flip_count * log_factor) * log_scaler; - double min_alpha = item.sigs.empty() ? min_alpha_no_signal : min_alpha_with_signal; - alpha = std::clamp(normalized_alpha, min_alpha, max_alpha); - } - + int val = ((binary[i] >> (7 - j)) & 1) != 0 ? 1 : 0; + // Bit update frequency based highlighting + double offset = !item.sigs.empty() ? 50 : 0; + auto n = last_msg.last_changes[i].bit_change_counts[j]; + double min_f = n == 0 ? offset : offset + 25; + double alpha = std::clamp(offset + log2(1.0 + factor * (double)n / (double)last_msg.count) * scaler, min_f, max_f); auto color = item.bg_color; color.setAlpha(alpha); - updateItem(i, j, bit_val, color); + updateItem(i, j, val, color); } updateItem(i, 8, binary[i], last_msg.colors[i]); } } -const std::vector> &BinaryViewModel::getBitFlipChanges(size_t msg_size) { - // Return cached results if time range and data are unchanged - auto time_range = can->timeRange(); - if (bit_flip_tracker.time_range == time_range && !bit_flip_tracker.flip_counts.empty()) - return bit_flip_tracker.flip_counts; - - bit_flip_tracker.time_range = time_range; - bit_flip_tracker.flip_counts.assign(msg_size, std::array{}); - - // Iterate over events within the specified time range and calculate bit flips - auto [first, last] = can->eventsInRange(msg_id, time_range); - if (std::distance(first, last) <= 1) return bit_flip_tracker.flip_counts; - - std::vector prev_values((*first)->dat, (*first)->dat + (*first)->size); - for (auto it = std::next(first); it != last; ++it) { - const CanEvent *event = *it; - int size = std::min(msg_size, event->size); - for (int i = 0; i < size; ++i) { - const uint8_t diff = event->dat[i] ^ prev_values[i]; - if (!diff) continue; - - auto &bit_flips = bit_flip_tracker.flip_counts[i]; - for (int bit = 0; bit < 8; ++bit) { - if (diff & (1u << bit)) ++bit_flips[7 - bit]; - } - prev_values[i] = event->dat[i]; - } - } - - return bit_flip_tracker.flip_counts; -} - QVariant BinaryViewModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Vertical) { switch (role) { @@ -437,7 +388,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->fillRect(option.rect, item->bg_color); } auto color_role = item->sigs.contains(bin_view->hovered_sig) ? QPalette::BrightText : QPalette::Text; - painter->setPen(option.palette.color(bin_view->is_message_active ? QPalette::Normal : QPalette::Disabled, color_role)); + painter->setPen(option.palette.color(color_role)); } if (item->sigs.size() > 1) { diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 920deb0018..584910dc83 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -39,12 +39,6 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const override { return (index.column() == column_count - 1) ? Qt::ItemIsEnabled : Qt::ItemIsEnabled | Qt::ItemIsSelectable; } - const std::vector> &getBitFlipChanges(size_t msg_size); - - struct BitFlipTracker { - std::optional> time_range; - std::vector> flip_counts; - } bit_flip_tracker; struct Item { QColor bg_color = QColor(102, 86, 169, 255); @@ -55,7 +49,7 @@ public: bool valid = false; }; std::vector items; - bool heatmap_live_mode = true; + MessageId msg_id; int row_count = 0; const int column_count = 9; @@ -69,13 +63,8 @@ public: void setMessage(const MessageId &message_id); void highlight(const cabana::Signal *sig); QSet getOverlappingSignals() const; - void updateState() { model->updateState(); } - void paintEvent(QPaintEvent *event) override { - is_message_active = can->isMessageActive(model->msg_id); - QTableView::paintEvent(event); - } + inline void updateState() { model->updateState(); } QSize minimumSizeHint() const override; - void setHeatmapLiveMode(bool live) { model->heatmap_live_mode = live; updateState(); } signals: void signalClicked(const cabana::Signal *sig); @@ -97,7 +86,6 @@ private: QModelIndex anchor_index; BinaryViewModel *model; BinaryItemDelegate *delegate; - bool is_message_active = false; const cabana::Signal *resize_sig = nullptr; const cabana::Signal *hovered_sig = nullptr; friend class BinaryItemDelegate; diff --git a/tools/cabana/chart/chart.cc b/tools/cabana/chart/chart.cc index 3588c5edc6..6c13252e80 100644 --- a/tools/cabana/chart/chart.cc +++ b/tools/cabana/chart/chart.cc @@ -842,8 +842,6 @@ void ChartView::setSeriesType(SeriesType type) { } updateSeriesPoints(); updateTitle(); - - menu->actions()[(int)type]->setChecked(true); } } diff --git a/tools/cabana/chart/chartswidget.cc b/tools/cabana/chart/chartswidget.cc index 08840f4663..e2f0d4d0c9 100644 --- a/tools/cabana/chart/chartswidget.cc +++ b/tools/cabana/chart/chartswidget.cc @@ -23,7 +23,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { main_layout->setSpacing(0); // toolbar - toolbar = new QToolBar(tr("Charts"), this); + QToolBar *toolbar = new QToolBar(tr("Charts"), this); int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize); toolbar->setIconSize({icon_size, icon_size}); @@ -34,21 +34,6 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { toolbar->addWidget(title_label = new QLabel()); title_label->setContentsMargins(0, 0, style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0); - auto chart_type_action = toolbar->addAction(""); - QMenu *chart_type_menu = new QMenu(this); - auto types = std::array{tr("Line"), tr("Step"), tr("Scatter")}; - for (int i = 0; i < types.size(); ++i) { - QString type_text = types[i]; - chart_type_menu->addAction(type_text, this, [=]() { - settings.chart_series_type = i; - chart_type_action->setText("Type: " + type_text); - settingChanged(); - }); - } - chart_type_action->setText("Type: " + types[settings.chart_series_type]); - chart_type_action->setMenu(chart_type_menu); - qobject_cast(toolbar->widgetForAction(chart_type_action))->setPopupMode(QToolButton::InstantPopup); - QMenu *menu = new QMenu(this); for (int i = 0; i < MAX_COLUMN_COUNT; ++i) { menu->addAction(tr("%1").arg(i + 1), [=]() { setColumnCount(i + 1); }); @@ -57,13 +42,13 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { columns_action->setMenu(menu); qobject_cast(toolbar->widgetForAction(columns_action))->setPopupMode(QToolButton::InstantPopup); - QWidget *spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - toolbar->addWidget(spacer); + QLabel *stretch_label = new QLabel(this); + stretch_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + toolbar->addWidget(stretch_label); range_lb_action = toolbar->addWidget(range_lb = new QLabel(this)); range_slider = new LogSlider(1000, Qt::Horizontal, this); - range_slider->setFixedWidth(150 * qApp->devicePixelRatio()); + range_slider->setMaximumWidth(200); range_slider->setToolTip(tr("Set the chart range")); range_slider->setRange(1, settings.max_cached_minutes * 60); range_slider->setSingleStep(1); @@ -136,12 +121,10 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { setIsDocked(true); newTab(); qApp->installEventFilter(this); + setWhatsThis(tr(R"( - Chart View
- Click: Click to seek to a corresponding time.
- Drag: Zoom into the chart.
- Shift + Drag: Scrub through the chart to view values.
- Right Mouse: Open the context menu.
+ Chart view
+ )")); } @@ -193,7 +176,6 @@ QRect ChartsWidget::chartVisibleRect(ChartView *chart) { } void ChartsWidget::showValueTip(double sec) { - emit showTip(sec); if (sec < 0 && !value_tip_visible_) return; value_tip_visible_ = sec >= 0; @@ -237,7 +219,7 @@ void ChartsWidget::setIsDocked(bool docked) { void ChartsWidget::updateToolBar() { title_label->setText(tr("Charts: %1").arg(charts.size())); - columns_action->setText(tr("Columns: %1").arg(column_count)); + columns_action->setText(tr("Column: %1").arg(column_count)); range_lb->setText(utils::formatSeconds(max_chart_range)); bool is_zoomed = can->timeRange().has_value(); @@ -259,9 +241,7 @@ void ChartsWidget::settingChanged() { c->setTheme(theme); } } - if (range_slider->maximum() != settings.max_cached_minutes * 60) { - range_slider->setRange(1, settings.max_cached_minutes * 60); - } + range_slider->setRange(1, settings.max_cached_minutes * 60); for (auto c : charts) { c->setFixedHeight(settings.chart_height); c->setSeriesType((SeriesType)settings.chart_series_type); @@ -400,7 +380,7 @@ void ChartsWidget::doAutoScroll() { } QSize ChartsWidget::minimumSizeHint() const { - return QSize(CHART_MIN_WIDTH * 1.5 * qApp->devicePixelRatio(), QWidget::minimumSizeHint().height()); + return QSize(CHART_MIN_WIDTH, QWidget::minimumSizeHint().height()); } void ChartsWidget::newChart() { @@ -549,14 +529,20 @@ void ChartsContainer::dropEvent(QDropEvent *event) { void ChartsContainer::paintEvent(QPaintEvent *ev) { if (!drop_indictor_pos.isNull() && !childAt(drop_indictor_pos)) { - QRect r = geometry(); - r.setHeight(CHART_SPACING); + QRect r; if (auto insert_after = getDropAfter(drop_indictor_pos)) { - r.moveTop(insert_after->geometry().bottom()); + QRect area = insert_after->geometry(); + r = QRect(area.left(), area.bottom() + 1, area.width(), CHART_SPACING); + } else { + r = geometry(); + r.setHeight(CHART_SPACING); } QPainter p(this); - p.fillRect(r, palette().highlight()); + p.setPen(QPen(palette().highlight(), 2)); + p.drawLine(r.topLeft() + QPoint(1, 0), r.bottomLeft() + QPoint(1, 0)); + p.drawLine(r.topLeft() + QPoint(0, r.height() / 2), r.topRight() + QPoint(0, r.height() / 2)); + p.drawLine(r.topRight(), r.bottomRight()); } } diff --git a/tools/cabana/chart/chartswidget.h b/tools/cabana/chart/chartswidget.h index 46e7f546b0..bfdaaaa954 100644 --- a/tools/cabana/chart/chartswidget.h +++ b/tools/cabana/chart/chartswidget.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -53,7 +52,6 @@ public slots: signals: void toggleChartsDocking(); void seriesChanged(); - void showTip(double seconds); private: QSize minimumSizeHint() const override; @@ -90,7 +88,6 @@ private: bool is_docked = true; ToolButton *dock_btn; - QToolBar *toolbar; QAction *undo_zoom_action; QAction *redo_zoom_action; QAction *reset_zoom_action; diff --git a/tools/cabana/chart/sparkline.cc b/tools/cabana/chart/sparkline.cc index 09f86a095a..094fe96182 100644 --- a/tools/cabana/chart/sparkline.cc +++ b/tools/cabana/chart/sparkline.cc @@ -5,9 +5,15 @@ #include void Sparkline::update(const MessageId &msg_id, const cabana::Signal *sig, double last_msg_ts, int range, QSize size) { + const auto &msgs = can->events(msg_id); + + auto range_start = can->toMonoTime(last_msg_ts - range); + auto range_end = can->toMonoTime(last_msg_ts); + auto first = std::lower_bound(msgs.cbegin(), msgs.cend(), range_start, CompareCanEvent()); + auto last = std::upper_bound(first, msgs.cend(), range_end, CompareCanEvent()); + points.clear(); double value = 0; - auto [first, last] = can->eventsInRange(msg_id, std::make_pair(last_msg_ts -range, last_msg_ts)); for (auto it = first; it != last; ++it) { if (sig->getValue((*it)->dat, (*it)->size, &value)) { points.emplace_back(((*it)->mono_time - (*first)->mono_time) / 1e9, value); diff --git a/tools/cabana/dbc/dbc.cc b/tools/cabana/dbc/dbc.cc index ba979f258c..149bb9f59a 100644 --- a/tools/cabana/dbc/dbc.cc +++ b/tools/cabana/dbc/dbc.cc @@ -45,7 +45,6 @@ cabana::Msg &cabana::Msg::operator=(const cabana::Msg &other) { name = other.name; size = other.size; comment = other.comment; - transmitter = other.transmitter; for (auto s : sigs) delete s; sigs.clear(); diff --git a/tools/cabana/dbc/dbc.h b/tools/cabana/dbc/dbc.h index d2b25bc5f2..da44319b5c 100644 --- a/tools/cabana/dbc/dbc.h +++ b/tools/cabana/dbc/dbc.h @@ -8,16 +8,16 @@ #include #include + const QString UNTITLED = "untitled"; const QString DEFAULT_NODE_NAME = "XXX"; -constexpr int CAN_MAX_DATA_BYTES = 64; struct MessageId { uint8_t source = 0; uint32_t address = 0; QString toString() const { - return QString("%1:%2").arg(source).arg(QString::number(address, 16).toUpper()); + return QString("%1:%2").arg(source).arg(address, 1, 16); } bool operator==(const MessageId &other) const { diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 2e213988bc..7befadb722 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -2,8 +2,7 @@ #include #include -#include -#include +#include #include "tools/cabana/commands.h" #include "tools/cabana/mainwin.h" @@ -21,7 +20,19 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart tabbar->setContextMenuPolicy(Qt::CustomContextMenu); main_layout->addWidget(tabbar); - createToolBar(); + // message title + QHBoxLayout *title_layout = new QHBoxLayout(); + title_layout->setContentsMargins(3, 6, 3, 0); + auto spacer = new QSpacerItem(0, 1); + title_layout->addItem(spacer); + title_layout->addWidget(name_label = new ElidedLabel(this), 1); + name_label->setStyleSheet("QLabel{font-weight:bold;}"); + name_label->setAlignment(Qt::AlignCenter); + auto edit_btn = new ToolButton("pencil", tr("Edit Message")); + title_layout->addWidget(edit_btn); + title_layout->addWidget(remove_btn = new ToolButton("x-lg", tr("Remove Message"))); + spacer->changeSize(edit_btn->sizeHint().width() * 2 + 9, 1); + main_layout->addLayout(title_layout); // warning warning_widget = new QWidget(this); @@ -47,6 +58,8 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart tab_widget->addTab(history_log = new LogsWidget(this), utils::icon("stopwatch"), "&Logs"); main_layout->addWidget(tab_widget); + QObject::connect(edit_btn, &QToolButton::clicked, this, &DetailWidget::editMsg); + QObject::connect(remove_btn, &QToolButton::clicked, this, &DetailWidget::removeMsg); QObject::connect(binary_view, &BinaryView::signalHovered, signal_view, &SignalView::signalHovered); QObject::connect(binary_view, &BinaryView::signalClicked, [this](const cabana::Signal *s) { signal_view->selectSignal(s, true); }); QObject::connect(binary_view, &BinaryView::editSignal, signal_view->model, &SignalModel::saveSignal); @@ -67,41 +80,6 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(charts, &ChartsWidget::seriesChanged, signal_view, &SignalView::updateChartState); } -void DetailWidget::createToolBar() { - QToolBar *toolbar = new QToolBar(this); - int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize); - toolbar->setIconSize({icon_size, icon_size}); - toolbar->addWidget(name_label = new ElidedLabel(this)); - name_label->setStyleSheet("QLabel{font-weight:bold;}"); - - QWidget *spacer = new QWidget(); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - toolbar->addWidget(spacer); - -// Heatmap label and radio buttons - toolbar->addWidget(new QLabel(tr("Heatmap:"), this)); - auto *heatmap_live = new QRadioButton(tr("Live"), this); - auto *heatmap_all = new QRadioButton(tr("All"), this); - heatmap_live->setChecked(true); - - toolbar->addWidget(heatmap_live); - toolbar->addWidget(heatmap_all); - - // Edit and remove buttons - toolbar->addSeparator(); - toolbar->addAction(utils::icon("pencil"), tr("Edit Message"), this, &DetailWidget::editMsg); - action_remove_msg = toolbar->addAction(utils::icon("x-lg"), tr("Remove Message"), this, &DetailWidget::removeMsg); - - layout()->addWidget(toolbar); - - connect(heatmap_live, &QAbstractButton::toggled, this, [this](bool on) { binary_view->setHeatmapLiveMode(on); }); - connect(can, &AbstractStream::timeRangeChanged, this, [=](const std::optional> &range) { - auto text = range ? QString("%1 - %2").arg(range->first, 0, 'f', 3).arg(range->second, 0, 'f', 3) : "All"; - heatmap_all->setText(text); - (range ? heatmap_all : heatmap_live)->setChecked(true); - }); -} - void DetailWidget::showTabBarContextMenu(const QPoint &pt) { int index = tabbar->tabAt(pt); if (index >= 0) { @@ -153,11 +131,14 @@ void DetailWidget::refresh() { for (auto s : binary_view->getOverlappingSignals()) { warnings.push_back(tr("%1 has overlapping bits.").arg(s->name)); } + } else { + warnings.push_back(tr("Drag-Select in binary view to create new signal.")); } + QString msg_name = msg ? QString("%1 (%2)").arg(msg->name, msg->transmitter) : msgName(msg_id); name_label->setText(msg_name); name_label->setToolTip(msg_name); - action_remove_msg->setEnabled(msg != nullptr); + remove_btn->setEnabled(msg != nullptr); if (!warnings.isEmpty()) { warning_label->setText(warnings.join('\n')); @@ -203,7 +184,8 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit name_edit->setValidator(new NameValidator(name_edit)); form_layout->addRow(tr("Size"), size_spin = new QSpinBox(this)); - size_spin->setRange(1, CAN_MAX_DATA_BYTES); + // TODO: limit the maximum? + size_spin->setMinimum(1); size_spin->setValue(size); form_layout->addRow(tr("Node"), node = new QLineEdit(this)); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 47304fbdc5..15e1ee5f2f 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -36,7 +36,6 @@ public: void refresh(); private: - void createToolBar(); void showTabBarContextMenu(const QPoint &pt); void editMsg(); void removeMsg(); @@ -48,7 +47,7 @@ private: QWidget *warning_widget; TabBar *tabbar; QTabWidget *tab_widget; - QAction *action_remove_msg; + QToolButton *remove_btn; LogsWidget *history_log; BinaryView *binary_view; SignalView *signal_view; diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 8361befb53..d3f868cd47 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -191,7 +191,6 @@ void MainWindow::createDockWidgets() { video_splitter->handle(1)->setEnabled(!can->liveStreaming()); video_dock->setWidget(video_splitter); QObject::connect(charts_widget, &ChartsWidget::toggleChartsDocking, this, &MainWindow::toggleChartsDocking); - QObject::connect(charts_widget, &ChartsWidget::showTip, video_widget, &VideoWidget::showThumbnail); } void MainWindow::createStatusBar() { diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index ed9aeaf311..ecb739a733 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -13,6 +13,21 @@ #include "tools/cabana/commands.h" +static bool isMessageActive(const MessageId &id) { + if (id.source == INVALID_SOURCE) { + return false; + } + // Check if the message is active based on time difference and frequency + const auto &m = can->lastMessage(id); + float delta = can->currentSec() - m.ts; + + if (m.freq < std::numeric_limits::epsilon()) { + return delta < 1.5; + } + + return delta < (5.0 / m.freq) + (1.0 / settings.fps); +} + MessagesWidget::MessagesWidget(QWidget *parent) : menu(new QMenu(this)), QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(0, 0, 0, 0); @@ -192,7 +207,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { switch (index.column()) { case Column::NAME: return item.name; case Column::SOURCE: return item.id.source != INVALID_SOURCE ? QString::number(item.id.source) : NA; - case Column::ADDRESS: return toHexString(item.id.address); + case Column::ADDRESS: return QString::number(item.id.address, 16); case Column::NODE: return item.node; case Column::FREQ: return item.id.source != INVALID_SOURCE ? getFreq(can->lastMessage(item.id).freq) : NA; case Column::COUNT: return item.id.source != INVALID_SOURCE ? QString::number(can->lastMessage(item.id).count) : NA; @@ -285,7 +300,7 @@ bool MessageListModel::match(const MessageListModel::Item &item) { match = parseRange(txt, item.id.source); break; case Column::ADDRESS: - match = toHexString(item.id.address).contains(txt, Qt::CaseInsensitive); + match = QString::number(item.id.address, 16).contains(txt, Qt::CaseInsensitive); match = match || parseRange(txt, item.id.address, 16); break; case Column::NODE: @@ -320,7 +335,7 @@ bool MessageListModel::filterAndSort() { std::vector items; items.reserve(all_messages.size()); for (const auto &id : all_messages) { - if (show_inactive_messages || can->isMessageActive(id)) { + if (show_inactive_messages || isMessageActive(id)) { auto msg = dbc()->msg(id); Item item = {.id = id, .name = msg ? msg->name : UNTITLED, @@ -363,7 +378,7 @@ void MessageListModel::sort(int column, Qt::SortOrder order) { void MessageView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const auto &item = ((MessageListModel*)model())->items_[index.row()]; - if (!can->isMessageActive(item.id)) { + if (!isMessageActive(item.id)) { QStyleOptionViewItem custom_option = option; custom_option.palette.setBrush(QPalette::Text, custom_option.palette.color(QPalette::Disabled, QPalette::Text)); auto color = QApplication::palette().color(QPalette::HighlightedText); diff --git a/tools/cabana/settings.cc b/tools/cabana/settings.cc index cccc9b6d9a..523cbf3be7 100644 --- a/tools/cabana/settings.cc +++ b/tools/cabana/settings.cc @@ -89,6 +89,10 @@ SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) { groupbox = new QGroupBox("Chart"); form_layout = new QFormLayout(groupbox); + form_layout->addRow(tr("Default Series Type"), chart_series_type = new QComboBox(this)); + chart_series_type->addItems({tr("Line"), tr("Step Line"), tr("Scatter")}); + chart_series_type->setCurrentIndex(settings.chart_series_type); + form_layout->addRow(tr("Chart Height"), chart_height = new QSpinBox(this)); chart_height->setRange(100, 500); chart_height->setSingleStep(10); @@ -128,6 +132,7 @@ void SettingsDlg::save() { } settings.fps = fps->value(); settings.max_cached_minutes = cached_minutes->value(); + settings.chart_series_type = chart_series_type->currentIndex(); settings.chart_height = chart_height->value(); settings.log_livestream = log_livestream->isChecked(); settings.log_path = log_path->text(); diff --git a/tools/cabana/signalview.cc b/tools/cabana/signalview.cc index 9fe70c3ee8..130b76d502 100644 --- a/tools/cabana/signalview.cc +++ b/tools/cabana/signalview.cc @@ -382,7 +382,7 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie } else if (item->type == SignalModel::Item::Size) { QSpinBox *spin = new QSpinBox(parent); spin->setFrame(false); - spin->setRange(1, CAN_MAX_DATA_BYTES); + spin->setRange(1, 64); return spin; } else if (item->type == SignalModel::Item::SignalType) { QComboBox *c = new QComboBox(parent); diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 2278104c26..7abeafea94 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -39,7 +39,7 @@ void AbstractStream::updateMasks() { const int size = std::min(mask.size(), m.last_changes.size()); for (int i = 0; i < size; ++i) { for (int j = 0; j < 8; ++j) { - if (((mask[i] >> (7 - j)) & 1) != 0) m.bit_flip_counts[i][j] = 0; + if (((mask[i] >> (7 - j)) & 1) != 0) m.last_changes[i].bit_change_counts[j] = 0; } } } @@ -59,9 +59,9 @@ size_t AbstractStream::suppressHighlighted() { if (dt < 2.0) { last_change.suppressed = true; } + last_change.bit_change_counts.fill(0); cnt += last_change.suppressed; } - for (auto &flip_counts : m.bit_flip_counts) flip_counts.fill(0); } return cnt; } @@ -127,22 +127,8 @@ const CanData &AbstractStream::lastMessage(const MessageId &id) const { return it != last_msgs.end() ? it->second : empty_data; } -bool AbstractStream::isMessageActive(const MessageId &id) const { - if (id.source == INVALID_SOURCE) { - return false; - } - // Check if the message is active based on time difference and frequency - const auto &m = lastMessage(id); - float delta = currentSec() - m.ts; - - if (m.freq < std::numeric_limits::epsilon()) { - return delta < 1.5; - } - - return delta < (5.0 / m.freq) + (1.0 / settings.fps); -} - void AbstractStream::updateLastMsgsTo(double sec) { + std::lock_guard lk(mutex_); current_sec_ = sec; uint64_t last_ts = toMonoTime(sec); std::unordered_map msgs; @@ -174,17 +160,10 @@ void AbstractStream::updateLastMsgsTo(double sec) { std::any_of(messages_.cbegin(), messages_.cend(), [this](const auto &m) { return !last_msgs.count(m.first); }); last_msgs = messages_; + mutex_.unlock(); + emit msgsReceived(nullptr, id_changed); - - std::lock_guard lk(mutex_); - seek_finished_ = true; - seek_finished_cv_.notify_one(); -} - -void AbstractStream::waitForSeekFinshed() { - std::unique_lock lock(mutex_); - seek_finished_cv_.wait(lock, [this]() { return seek_finished_; }); - seek_finished_ = false; + resumeStream(); } const CanEvent *AbstractStream::newEvent(uint64_t mono_time, const cereal::CanData::Reader &c) { @@ -221,15 +200,6 @@ void AbstractStream::mergeEvents(const std::vector &events) { } } -std::pair AbstractStream::eventsInRange(const MessageId &id, std::optional> time_range) const { - const auto &events = can->events(id); - if (!time_range) return {events.begin(), events.end()}; - - auto first = std::lower_bound(events.begin(), events.end(), can->toMonoTime(time_range->first), CompareCanEvent()); - auto last = std::upper_bound(events.begin(), events.end(), can->toMonoTime(time_range->second), CompareCanEvent()); - return {first, last}; -} - namespace { enum Color { GREYISH_BLUE, CYAN, RED}; @@ -249,7 +219,15 @@ inline QColor blend(const QColor &a, const QColor &b) { // Calculate the frequency from the past one minute data double calc_freq(const MessageId &msg_id, double current_sec) { - auto [first, last] = can->eventsInRange(msg_id, std::make_pair(current_sec - 59, current_sec)); + const auto &events = can->events(msg_id); + if (events.empty()) return 0.0; + + auto current_mono_time = can->toMonoTime(current_sec); + auto start_mono_time = can->toMonoTime(current_sec - 59); + + auto first = std::lower_bound(events.begin(), events.end(), start_mono_time, CompareCanEvent()); + auto last = std::upper_bound(first, events.end(), current_mono_time, CompareCanEvent()); + int count = std::distance(first, last); if (count <= 1) return 0.0; @@ -270,10 +248,9 @@ void CanData::compute(const MessageId &msg_id, const uint8_t *can_data, const in } if (dat.size() != size) { - dat.assign(can_data, can_data + size); + dat.resize(size); colors.assign(size, QColor(0, 0, 0, 0)); last_changes.resize(size); - bit_flip_counts.resize(size); std::for_each(last_changes.begin(), last_changes.end(), [current_sec](auto &c) { c.ts = current_sec; }); } else { constexpr int periodic_threshold = 10; @@ -305,11 +282,10 @@ void CanData::compute(const MessageId &msg_id, const uint8_t *can_data, const in } // Track bit level changes - auto &row_bit_flips = bit_flip_counts[i]; const uint8_t diff = (cur ^ last); for (int bit = 0; bit < 8; bit++) { if (diff & (1u << bit)) { - ++row_bit_flips[7 - bit]; + ++last_change.bit_change_counts[7 - bit]; } } diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index f35b19d34f..5ecf086c95 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -34,9 +33,9 @@ struct CanData { int delta = 0; int same_delta_counter = 0; bool suppressed = false; + std::array bit_change_counts; }; std::vector last_changes; - std::vector> bit_flip_counts; double last_freq_update_ts = 0; }; @@ -54,7 +53,6 @@ struct CompareCanEvent { }; typedef std::unordered_map> MessageEventsMap; -using CanEventIter = std::vector::const_iterator; class AbstractStream : public QObject { Q_OBJECT @@ -83,12 +81,10 @@ public: inline double toSeconds(uint64_t mono_time) const { return std::max(0.0, (mono_time - beginMonoTime()) / 1e9); } inline const std::unordered_map &lastMessages() const { return last_msgs; } - bool isMessageActive(const MessageId &id) const; inline const MessageEventsMap &eventsMap() const { return events_; } inline const std::vector &allEvents() const { return all_events_; } const CanData &lastMessage(const MessageId &id) const; const std::vector &events(const MessageId &id) const; - std::pair eventsInRange(const MessageId &id, std::optional> time_range) const; size_t suppressHighlighted(); void clearSuppressed(); @@ -112,7 +108,7 @@ protected: void mergeEvents(const std::vector &events); const CanEvent *newEvent(uint64_t mono_time, const cereal::CanData::Reader &c); void updateEvent(const MessageId &id, double sec, const uint8_t *data, uint8_t size); - void waitForSeekFinshed(); + virtual void resumeStream() {} std::vector all_events_; double current_sec_ = 0; std::optional> time_range_; @@ -128,8 +124,6 @@ private: // Members accessed in multiple threads. (mutex protected) std::mutex mutex_; - std::condition_variable seek_finished_cv_; - bool seek_finished_ = false; std::set new_msgs_; std::unordered_map messages_; std::unordered_map> masks_; diff --git a/tools/cabana/streams/replaystream.cc b/tools/cabana/streams/replaystream.cc index ebe478ded7..bfe5ca74da 100644 --- a/tools/cabana/streams/replaystream.cc +++ b/tools/cabana/streams/replaystream.cc @@ -53,12 +53,9 @@ bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint // Forward replay callbacks to corresponding Qt signals. replay->onSeeking = [this](double sec) { emit seeking(sec); }; - replay->onSeekedTo = [this](double sec) { - emit seekedTo(sec); - waitForSeekFinshed(); - }; + replay->onSeekedTo = [this](double sec) { emit seekedTo(sec); }; replay->onQLogLoaded = [this](std::shared_ptr qlog) { emit qLogLoaded(qlog); }; - replay->onSegmentsMerged = [this]() { QMetaObject::invokeMethod(this, &ReplayStream::mergeSegments, Qt::BlockingQueuedConnection); }; + replay->onSegmentsMerged = [this]() { QMetaObject::invokeMethod(this, &ReplayStream::mergeSegments, Qt::QueuedConnection); }; bool success = replay->load(); if (!success) { diff --git a/tools/cabana/streams/replaystream.h b/tools/cabana/streams/replaystream.h index df1f2526a5..2d7f335193 100644 --- a/tools/cabana/streams/replaystream.h +++ b/tools/cabana/streams/replaystream.h @@ -32,6 +32,7 @@ public: inline float getSpeed() const { return replay->getSpeed(); } inline Replay *getReplay() const { return replay.get(); } inline bool isPaused() const override { return replay->isPaused(); } + void resumeStream() override { return replay->resumeStream(); } void pause(bool pause) override; signals: diff --git a/tools/cabana/utils/util.h b/tools/cabana/utils/util.h index 1aad3103db..0ebd7e41f8 100644 --- a/tools/cabana/utils/util.h +++ b/tools/cabana/utils/util.h @@ -163,4 +163,3 @@ private: int num_decimals(double num); QString signalToolTip(const cabana::Signal *sig); -inline QString toHexString(int value) { return QString("0x%1").arg(QString::number(value, 16).toUpper(), 2, '0'); } diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index e792f80a41..0b2beb1dd6 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -31,12 +31,9 @@ static Replay *getReplay() { VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { setFrameStyle(QFrame::StyledPanel | QFrame::Plain); auto main_layout = new QVBoxLayout(this); - main_layout->setContentsMargins(0, 0, 0, 0); - main_layout->setSpacing(0); if (!can->liveStreaming()) main_layout->addWidget(createCameraWidget()); - - createPlaybackController(); + main_layout->addLayout(createPlaybackController()); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); @@ -68,19 +65,15 @@ VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { timeline_colors[(int)TimelineType::AlertCritical].name())); } -void VideoWidget::createPlaybackController() { - QToolBar *toolbar = new QToolBar(this); - layout()->addWidget(toolbar); - - int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize); - toolbar->setIconSize({icon_size, icon_size}); - - toolbar->addAction(utils::icon("rewind"), tr("Seek backward"), []() { can->seekTo(can->currentSec() - 1); }); - play_toggle_action = toolbar->addAction(utils::icon("play"), tr("Play"), []() { can->pause(!can->isPaused()); }); - toolbar->addAction(utils::icon("fast-forward"), tr("Seek forward"), []() { can->seekTo(can->currentSec() + 1); }); +QHBoxLayout *VideoWidget::createPlaybackController() { + QHBoxLayout *layout = new QHBoxLayout(); + layout->addWidget(seek_backward_btn = new ToolButton("rewind", tr("Seek backward"))); + layout->addWidget(play_btn = new ToolButton("play", tr("Play"))); + layout->addWidget(seek_forward_btn = new ToolButton("fast-forward", tr("Seek forward"))); if (can->liveStreaming()) { - skip_to_end_action = toolbar->addAction(utils::icon("skip-end"), tr("Skip to the end"), this, [this]() { + layout->addWidget(skip_to_end_btn = new ToolButton("skip-end", tr("Skip to the end"), this)); + QObject::connect(skip_to_end_btn, &QToolButton::clicked, [this]() { // set speed to 1.0 speed_btn->menu()->actions()[7]->setChecked(true); can->pause(false); @@ -88,48 +81,53 @@ void VideoWidget::createPlaybackController() { }); } - time_display_action = toolbar->addAction("", this, [this]() { - settings.absolute_time = !settings.absolute_time; - time_display_action->setToolTip(settings.absolute_time ? tr("Elapsed time") : tr("Absolute time")); - updateState(); - }); - - QWidget *spacer = new QWidget(); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - toolbar->addWidget(spacer); + layout->addWidget(time_btn = new QToolButton); + time_btn->setToolTip(settings.absolute_time ? tr("Elapsed time") : tr("Absolute time")); + time_btn->setAutoRaise(true); + layout->addStretch(0); if (!can->liveStreaming()) { - toolbar->addAction(utils::icon("repeat"), tr("Loop playback"), this, &VideoWidget::loopPlaybackClicked); + layout->addWidget(loop_btn = new ToolButton("repeat", tr("Loop playback"))); + QObject::connect(loop_btn, &QToolButton::clicked, this, &VideoWidget::loopPlaybackClicked); } - createSpeedDropdown(toolbar); -} - -void VideoWidget::createSpeedDropdown(QToolBar *toolbar) { - toolbar->addWidget(speed_btn = new QToolButton(this)); + // speed selector + layout->addWidget(speed_btn = new QToolButton(this)); + speed_btn->setAutoRaise(true); speed_btn->setMenu(new QMenu(speed_btn)); speed_btn->setPopupMode(QToolButton::InstantPopup); QActionGroup *speed_group = new QActionGroup(this); speed_group->setExclusive(true); - for (float speed : {0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 0.8, 1., 2., 3., 5.}) { - auto act = speed_btn->menu()->addAction(QString("%1x").arg(speed), this, [this, speed]() { - can->setSpeed(speed); - speed_btn->setText(QString("%1x ").arg(speed)); - }); - - speed_group->addAction(act); - act->setCheckable(true); - if (speed == 1.0) { - act->setChecked(true); - act->trigger(); - } - } - + int max_width = 0; QFont font = speed_btn->font(); font.setBold(true); speed_btn->setFont(font); - speed_btn->setMinimumWidth(speed_btn->fontMetrics().width("0.05x ") + style()->pixelMetric(QStyle::PM_MenuButtonIndicator)); + QFontMetrics fm(font); + for (float speed : {0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 0.8, 1., 2., 3., 5.}) { + QString name = QString("%1x").arg(speed); + max_width = std::max(max_width, fm.width(name) + fm.horizontalAdvance(QLatin1Char(' ')) * 2); + + QAction *act = new QAction(name, speed_group); + act->setCheckable(true); + QObject::connect(act, &QAction::toggled, [this, speed]() { + can->setSpeed(speed); + speed_btn->setText(QString("%1x ").arg(speed)); + }); + speed_btn->menu()->addAction(act); + if (speed == 1.0)act->setChecked(true); + } + speed_btn->setMinimumWidth(max_width + style()->pixelMetric(QStyle::PM_MenuButtonIndicator)); + + QObject::connect(play_btn, &QToolButton::clicked, []() { can->pause(!can->isPaused()); }); + QObject::connect(seek_backward_btn, &QToolButton::clicked, []() { can->seekTo(can->currentSec() - 1); }); + QObject::connect(seek_forward_btn, &QToolButton::clicked, []() { can->seekTo(can->currentSec() + 1); }); + QObject::connect(time_btn, &QToolButton::clicked, [this]() { + settings.absolute_time = !settings.absolute_time; + time_btn->setToolTip(settings.absolute_time ? tr("Elapsed time") : tr("Absolute time")); + updateState(); + }); + return layout; } QWidget *VideoWidget::createCameraWidget() { @@ -152,6 +150,7 @@ QWidget *VideoWidget::createCameraWidget() { QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->currentSecond()); }); QObject::connect(can, &AbstractStream::paused, cam_widget, [c = cam_widget]() { c->showPausedOverlay(); }); + QObject::connect(can, &AbstractStream::resume, cam_widget, [c = cam_widget]() { c->update(); }); QObject::connect(can, &AbstractStream::eventsMerged, this, [this]() { slider->update(); }); QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); QObject::connect(cam_widget, &CameraWidget::vipcAvailableStreamsUpdated, this, &VideoWidget::vipcAvailableStreamsUpdated); @@ -159,7 +158,7 @@ QWidget *VideoWidget::createCameraWidget() { if (index != -1) cam_widget->setStreamType((VisionStreamType)camera_tab->tabData(index).toInt()); }); QObject::connect(static_cast(can), &ReplayStream::qLogLoaded, cam_widget, &StreamCameraView::parseQLog, Qt::QueuedConnection); - slider->installEventFilter(this); + slider->installEventFilter(cam_widget); return w; } @@ -181,13 +180,13 @@ void VideoWidget::vipcAvailableStreamsUpdated(std::set streams void VideoWidget::loopPlaybackClicked() { bool is_looping = getReplay()->loop(); getReplay()->setLoop(!is_looping); - qobject_cast(sender())->setIcon(utils::icon(!is_looping ? "repeat" : "repeat-1")); + loop_btn->setIcon(!is_looping ? "repeat" : "repeat-1"); } void VideoWidget::timeRangeChanged() { const auto time_range = can->timeRange(); if (can->liveStreaming()) { - skip_to_end_action->setEnabled(!time_range.has_value()); + skip_to_end_btn->setEnabled(!time_range.has_value()); return; } time_range ? slider->setTimeRange(time_range->first, time_range->second) @@ -209,50 +208,28 @@ void VideoWidget::updateState() { if (camera_tab->count() == 0) { // No streams available cam_widget->update(); // Manually refresh to show alert events } - time_display_action->setText(QString("%1 / %2").arg(formatTime(can->currentSec(), true), + time_btn->setText(QString("%1 / %2").arg(formatTime(can->currentSec(), true), formatTime(slider->maximum() / slider->factor))); } else { - time_display_action->setText(formatTime(can->currentSec(), true)); + time_btn->setText(formatTime(can->currentSec(), true)); } } void VideoWidget::updatePlayBtnState() { - play_toggle_action->setIcon(utils::icon(can->isPaused() ? "play" : "pause")); - play_toggle_action->setToolTip(can->isPaused() ? tr("Play") : tr("Pause")); -} - -void VideoWidget::showThumbnail(double seconds) { - if (can->liveStreaming()) return; - - cam_widget->thumbnail_dispaly_time = seconds; - slider->thumbnail_dispaly_time = seconds; - cam_widget->update(); - slider->update(); -} - -bool VideoWidget::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::MouseMove) { - auto [min_sec, max_sec] = can->timeRange().value_or(std::make_pair(can->minSeconds(), can->maxSeconds())); - showThumbnail(min_sec + static_cast(event)->pos().x() * (max_sec - min_sec) / slider->width()); - } else if (event->type() == QEvent::Leave) { - showThumbnail(-1); - } - return false; + play_btn->setIcon(can->isPaused() ? "play" : "pause"); + play_btn->setToolTip(can->isPaused() ? tr("Play") : tr("Pause")); } // Slider + Slider::Slider(QWidget *parent) : QSlider(Qt::Horizontal, parent) { setMouseTracking(true); } void Slider::paintEvent(QPaintEvent *ev) { QPainter p(this); - - QStyleOptionSlider opt; - initStyleOption(&opt); - QRect r = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this); + QRect r = rect().adjusted(0, 4, 0, -4); p.fillRect(r, timeline_colors[(int)TimelineType::None]); - double min = minimum() / factor; double max = maximum() / factor; @@ -277,19 +254,13 @@ void Slider::paintEvent(QPaintEvent *ev) { } } + QStyleOptionSlider opt; + opt.initFrom(this); opt.minimum = minimum(); opt.maximum = maximum(); opt.subControls = QStyle::SC_SliderHandle; opt.sliderPosition = value(); style()->drawComplexControl(QStyle::CC_Slider, &opt, &p); - - if (thumbnail_dispaly_time >= 0) { - int left = (thumbnail_dispaly_time - min) * width() / (max - min) - 1; - QRect rc(left, rect().top() + 1, 2, rect().height() - 2); - p.setBrush(palette().highlight()); - p.setPen(Qt::NoPen); - p.drawRoundedRect(rc, 1.5, 1.5); - } } void Slider::mousePressEvent(QMouseEvent *e) { @@ -301,6 +272,7 @@ void Slider::mousePressEvent(QMouseEvent *e) { } // StreamCameraView + StreamCameraView::StreamCameraView(std::string stream_name, VisionStreamType stream_type, QWidget *parent) : CameraWidget(stream_name, stream_type, parent) { fade_animation = new QPropertyAnimation(this, "overlayOpacity"); @@ -322,7 +294,6 @@ void StreamCameraView::parseQLog(std::shared_ptr qlog) { QPixmap generated_thumb = generateThumbnail(thumb, can->toSeconds(thumb_data.getTimestampEof())); std::lock_guard lock(mutex); thumbnails[thumb_data.getTimestampEof()] = generated_thumb; - big_thumbnails[thumb_data.getTimestampEof()] = thumb; } } }); @@ -333,15 +304,12 @@ void StreamCameraView::paintGL() { CameraWidget::paintGL(); QPainter p(this); - bool scrubbing = false; - if (thumbnail_dispaly_time >= 0) { - scrubbing = can->isPaused(); - scrubbing ? drawScrubThumbnail(p) : drawThumbnail(p); - } - if (auto alert = getReplay()->findAlertAtTime(scrubbing ? thumbnail_dispaly_time : can->currentSec())) { + if (auto alert = getReplay()->findAlertAtTime(can->currentSec())) { drawAlert(p, rect(), *alert); } - + if (thumbnail_pt_) { + drawThumbnail(p); + } if (can->isPaused()) { p.setPen(QColor(200, 200, 200, static_cast(255 * fade_animation->currentValue().toFloat()))); p.setFont(QFont(font().family(), 16, QFont::Bold)); @@ -361,37 +329,25 @@ QPixmap StreamCameraView::generateThumbnail(QPixmap thumb, double seconds) { return scaled; } -void StreamCameraView::drawScrubThumbnail(QPainter &p) { - p.fillRect(rect(), Qt::black); - auto it = big_thumbnails.lowerBound(can->toMonoTime(thumbnail_dispaly_time)); - if (it != big_thumbnails.end()) { - QPixmap scaled_thumb = it.value().scaled(rect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - QRect thumb_rect(rect().center() - scaled_thumb.rect().center(), scaled_thumb.size()); - p.drawPixmap(thumb_rect.topLeft(), scaled_thumb); - drawTime(p, thumb_rect, thumbnail_dispaly_time); - } -} - void StreamCameraView::drawThumbnail(QPainter &p) { - auto it = thumbnails.lowerBound(can->toMonoTime(thumbnail_dispaly_time)); + int pos = std::clamp(thumbnail_pt_->x(), 0, width()); + auto [min_sec, max_sec] = can->timeRange().value_or(std::make_pair(can->minSeconds(), can->maxSeconds())); + double seconds = min_sec + pos * (max_sec - min_sec) / width(); + + auto it = thumbnails.lowerBound(can->toMonoTime(seconds)); if (it != thumbnails.end()) { const QPixmap &thumb = it.value(); - auto [min_sec, max_sec] = can->timeRange().value_or(std::make_pair(can->minSeconds(), can->maxSeconds())); - int pos = (thumbnail_dispaly_time - min_sec) * width() / (max_sec - min_sec); int x = std::clamp(pos - thumb.width() / 2, THUMBNAIL_MARGIN, width() - thumb.width() - THUMBNAIL_MARGIN + 1); int y = height() - thumb.height() - THUMBNAIL_MARGIN; p.drawPixmap(x, y, thumb); - drawTime(p, QRect{x, y, thumb.width(), thumb.height()}, thumbnail_dispaly_time); + p.setPen(QPen(palette().color(QPalette::BrightText), 2)); + p.setFont(QFont(font().family(), 10)); + p.drawText(x, y, thumb.width(), thumb.height() - THUMBNAIL_MARGIN, + Qt::AlignHCenter | Qt::AlignBottom, QString::number(seconds, 'f', 3)); } } -void StreamCameraView::drawTime(QPainter &p, const QRect &rect, double seconds) { - p.setPen(palette().color(QPalette::BrightText)); - p.setFont(QFont(font().family(), 10)); - p.drawText(rect.adjusted(0, 0, 0, -THUMBNAIL_MARGIN), Qt::AlignHCenter | Qt::AlignBottom, QString::number(seconds, 'f', 3)); -} - void StreamCameraView::drawAlert(QPainter &p, const QRect &rect, const Timeline::Entry &alert) { p.setPen(QPen(palette().color(QPalette::BrightText), 2)); QColor color = timeline_colors[int(alert.type)]; @@ -404,3 +360,14 @@ void StreamCameraView::drawAlert(QPainter &p, const QRect &rect, const Timeline: p.fillRect(text_rect.left(), r.top(), text_rect.width(), r.height(), color); p.drawText(text_rect, Qt::AlignTop | Qt::AlignHCenter | Qt::TextWordWrap, text); } + +bool StreamCameraView::eventFilter(QObject *, QEvent *event) { + if (event->type() == QEvent::MouseMove) { + thumbnail_pt_ = static_cast(event)->pos(); + update(); + } else if (event->type() == QEvent::Leave) { + thumbnail_pt_ = std::nullopt; + update(); + } + return false; +} diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index 1d87a5cfa0..78503365e5 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -1,14 +1,15 @@ #pragma once #include +#include #include #include #include +#include #include #include #include -#include #include #include "selfdrive/ui/qt/widgets/cameraview.h" @@ -27,7 +28,6 @@ public: void mousePressEvent(QMouseEvent *e) override; void paintEvent(QPaintEvent *ev) override; const double factor = 1000.0; - double thumbnail_dispaly_time = -1; }; class StreamCameraView : public CameraWidget { @@ -43,14 +43,11 @@ private: QPixmap generateThumbnail(QPixmap thumbnail, double seconds); void drawAlert(QPainter &p, const QRect &rect, const Timeline::Entry &alert); void drawThumbnail(QPainter &p); - void drawScrubThumbnail(QPainter &p); - void drawTime(QPainter &p, const QRect &rect, double seconds); + bool eventFilter(QObject *obj, QEvent *event) override; QPropertyAnimation *fade_animation; - QMap big_thumbnails; QMap thumbnails; - double thumbnail_dispaly_time = -1; - friend class VideoWidget; + std::optional thumbnail_pt_; }; class VideoWidget : public QFrame { @@ -58,25 +55,25 @@ class VideoWidget : public QFrame { public: VideoWidget(QWidget *parnet = nullptr); - void showThumbnail(double seconds); protected: - bool eventFilter(QObject *obj, QEvent *event) override; QString formatTime(double sec, bool include_milliseconds = false); void timeRangeChanged(); void updateState(); void updatePlayBtnState(); QWidget *createCameraWidget(); - void createPlaybackController(); - void createSpeedDropdown(QToolBar *toolbar); + QHBoxLayout *createPlaybackController(); void loopPlaybackClicked(); void vipcAvailableStreamsUpdated(std::set streams); StreamCameraView *cam_widget; - QAction *time_display_action = nullptr; - QAction *play_toggle_action = nullptr; + QToolButton *time_btn = nullptr; + ToolButton *seek_backward_btn = nullptr; + ToolButton *play_btn = nullptr; + ToolButton *seek_forward_btn = nullptr; + ToolButton *loop_btn = nullptr; QToolButton *speed_btn = nullptr; - QAction *skip_to_end_action = nullptr; + ToolButton *skip_to_end_btn = nullptr; Slider *slider = nullptr; QTabBar *camera_tab = nullptr; }; diff --git a/tools/install_python_dependencies.sh b/tools/install_python_dependencies.sh index b0bb835e64..267577d712 100755 --- a/tools/install_python_dependencies.sh +++ b/tools/install_python_dependencies.sh @@ -10,11 +10,8 @@ cd "$ROOT" # updating uv on macOS results in 403 sometimes function update_uv() { - if ! uv self update --help >/dev/null 2>&1; then - return 0 - fi - - for i in $(seq 1 5); do + for i in $(seq 1 5); + do if uv self update; then return 0 else diff --git a/tools/latencylogger/README.md b/tools/latencylogger/README.md new file mode 100644 index 0000000000..110970308a --- /dev/null +++ b/tools/latencylogger/README.md @@ -0,0 +1,90 @@ +# LatencyLogger + +LatencyLogger is a tool to track the time from first pixel to actuation. Timestamps are printed in a table as well as plotted in a graph. Start openpilot with `LOG_TIMESTAMPS=1` set to enable the necessary logging. + +## Usage + +``` +$ python3 latency_logger.py -h +usage: latency_logger.py [-h] [--relative] [--demo] [--plot] [route_or_segment_name] + +A tool for analyzing openpilot's end-to-end latency + +positional arguments: + route_or_segment_name + The route to print (default: None) + +optional arguments: + -h, --help show this help message and exit + --relative Make timestamps relative to the start of each frame (default: False) + --demo Use the demo route instead of providing one (default: False) + --plot If a plot should be generated (default: False) + --offset Offset service to better visualize overlap (default: False) +``` +To timestamp an event, use `LOGT("msg")` in c++ code or `cloudlog.timestamp("msg")` in python code. If the print is warning for frameId assignment ambiguity, use `LOGT(frameId ,"msg")`. + +## Examples + +Timestamps are visualized as diamonds + +| | Relative | Absolute | +| ------------- | ------------- | ------------- | +| Inline | ![inrel](https://user-images.githubusercontent.com/42323981/170559939-465df3b1-bf87-46d5-b5ee-5cc87dc49470.png) | ![inabs](https://user-images.githubusercontent.com/42323981/170559985-a82f87e7-82c4-4e48-a348-4221568dd589.png) | +| Offset | ![offrel](https://user-images.githubusercontent.com/42323981/170559854-93fba90f-acc4-4d08-b317-d3f8fc649ea8.png) | ![offabs](https://user-images.githubusercontent.com/42323981/170559782-06ed5599-d4e3-4701-ad78-5c1eec6cb61e.png) | + +Printed timestamps of a frame with internal durations. +``` +Frame ID: 1202 + camerad + wideRoadCameraState start of frame 0.0 + roadCameraState start of frame 0.049583 + wideRoadCameraState published 35.01206 + WideRoadCamera: Image set 35.020028 + roadCameraState published 38.508261 + RoadCamera: Image set 38.520344 + RoadCamera: Transformed 38.616176 + wideRoadCameraState.processingTime 3.152403049170971 + roadCameraState.processingTime 6.453451234847307 + modeld + Image added 40.909841 + Extra image added 42.515027 + Execution finished 63.002552 + modelV2 published 63.148747 + modelV2.modelExecutionTime 23.62649142742157 + modelV2.gpuExecutionTimeDEPRECATED 0.0 + plannerd + longitudinalPlan published 69.715999 + longitudinalPlan.solverExecutionTime 0.5619999719783664 + controlsd + Data sampled 70.217763 + Events updated 71.037178 + sendcan published 72.278775 + controlsState published 72.825226 + Data sampled 80.008354 + Events updated 80.787666 + sendcan published 81.849682 + controlsState published 82.238323 + Data sampled 90.521123 + Events updated 91.626003 + sendcan published 93.413218 + controlsState published 94.143989 + Data sampled 100.991497 + Events updated 101.973774 + sendcan published 103.565575 + controlsState published 104.146088 + Data sampled 110.284387 + Events updated 111.183541 + sendcan published 112.981692 + controlsState published 113.731994 + pandad + sending sendcan to panda: 250027001751393037323631 81.928119 + sendcan sent to panda: 250027001751393037323631 82.164834 + sending sendcan to panda: 250027001751393037323631 93.569986 + sendcan sent to panda: 250027001751393037323631 93.92795 + sending sendcan to panda: 250027001751393037323631 103.689167 + sendcan sent to panda: 250027001751393037323631 104.012235 + sending sendcan to panda: 250027001751393037323631 113.109555 + sendcan sent to panda: 250027001751393037323631 113.525487 + sending sendcan to panda: 250027001751393037323631 122.508434 + sendcan sent to panda: 250027001751393037323631 122.834314 +``` diff --git a/tools/latencylogger/latency_logger.py b/tools/latencylogger/latency_logger.py new file mode 100755 index 0000000000..65cb6e6c2c --- /dev/null +++ b/tools/latencylogger/latency_logger.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python3 +import argparse +import json +import matplotlib.patches as mpatches +import matplotlib.pyplot as plt +import sys +from bisect import bisect_left, bisect_right +from collections import defaultdict + +from openpilot.tools.lib.logreader import LogReader + +DEMO_ROUTE = "9f583b1d93915c31|2022-05-18--10-49-51--0" + +SERVICES = ['camerad', 'modeld', 'plannerd', 'controlsd', 'pandad'] +MONOTIME_KEYS = ['modelMonoTime', 'lateralPlanMonoTime'] +MSGQ_TO_SERVICE = { + 'roadCameraState': 'camerad', + 'wideRoadCameraState': 'camerad', + 'modelV2': 'modeld', + 'longitudinalPlan': 'plannerd', + 'sendcan': 'controlsd', + 'controlsState': 'controlsd' +} +SERVICE_TO_DURATIONS = { + 'camerad': ['processingTime'], + 'modeld': ['modelExecutionTime', 'gpuExecutionTimeDEPRECATED'], + 'plannerd': ['solverExecutionTime'], +} + +def read_logs(lr): + data = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) + mono_to_frame = {} + frame_mismatches = [] + frame_id_fails = 0 + latest_sendcan_monotime = 0 + for msg in lr: + if msg.which() == 'sendcan': + latest_sendcan_monotime = msg.logMonoTime + continue + + if msg.which() in MSGQ_TO_SERVICE: + service = MSGQ_TO_SERVICE[msg.which()] + msg_obj = getattr(msg, msg.which()) + + frame_id = -1 + if hasattr(msg_obj, "frameId"): + frame_id = msg_obj.frameId + else: + continue_outer = False + for key in MONOTIME_KEYS: + if hasattr(msg_obj, key): + if getattr(msg_obj, key) == 0: + # Filter out controlsd messages which arrive before the camera loop + continue_outer = True + elif getattr(msg_obj, key) in mono_to_frame: + frame_id = mono_to_frame[getattr(msg_obj, key)] + if continue_outer: + continue + if frame_id == -1: + frame_id_fails += 1 + continue + mono_to_frame[msg.logMonoTime] = frame_id + data['timestamp'][frame_id][service].append((msg.which()+" published", msg.logMonoTime)) + + next_service = SERVICES[SERVICES.index(service)+1] + if not data['start'][frame_id][next_service]: + data['start'][frame_id][next_service] = msg.logMonoTime + data['end'][frame_id][service] = msg.logMonoTime + + if service in SERVICE_TO_DURATIONS: + for duration in SERVICE_TO_DURATIONS[service]: + data['duration'][frame_id][service].append((msg.which()+"."+duration, getattr(msg_obj, duration))) + + if service == SERVICES[0]: + data['timestamp'][frame_id][service].append((msg.which()+" start of frame", msg_obj.timestampSof)) + if not data['start'][frame_id][service]: + data['start'][frame_id][service] = msg_obj.timestampSof + elif msg.which() == 'controlsState': + # Sendcan is published before controlsState, but the frameId is retrieved in CS + data['timestamp'][frame_id][service].append(("sendcan published", latest_sendcan_monotime)) + elif msg.which() == 'modelV2': + if msg_obj.frameIdExtra != frame_id: + frame_mismatches.append(frame_id) + + if frame_id_fails > 20: + print("Warning, many frameId fetch fails", frame_id_fails) + if len(frame_mismatches) > 20: + print("Warning, many frame mismatches", len(frame_mismatches)) + return (data, frame_mismatches) + +# This is not needed in 3.10 as a "key" parameter is added to bisect +class KeyifyList: + def __init__(self, inner, key): + self.inner = inner + self.key = key + def __len__(self): + return len(self.inner) + def __getitem__(self, k): + return self.key(self.inner[k]) + +def find_frame_id(time, service, start_times, end_times): + left = bisect_left(KeyifyList(list(start_times.items()), + lambda x: x[1][service] if x[1][service] else -1), time) - 1 + right = bisect_right(KeyifyList(list(end_times.items()), + lambda x: x[1][service] if x[1][service] else float("inf")), time) + return left, right + +def find_t0(start_times, frame_id=-1): + frame_id = frame_id if frame_id > -1 else min(start_times.keys()) + m = max(start_times.keys()) + while frame_id <= m: + for service in SERVICES: + if start_times[frame_id][service]: + return start_times[frame_id][service] + frame_id += 1 + raise Exception('No start time has been set') + +def insert_cloudlogs(lr, timestamps, start_times, end_times): + # at least one cloudlog must be made in controlsd + + t0 = find_t0(start_times) + failed_inserts = 0 + latest_controls_frameid = 0 + for msg in lr: + if msg.which() == "logMessage": + jmsg = json.loads(msg.logMessage) + if "timestamp" in jmsg['msg']: + time = int(jmsg['msg']['timestamp']['time']) + service = jmsg['ctx']['daemon'] + event = jmsg['msg']['timestamp']['event'] + if time < t0: + # Filter out controlsd messages which arrive before the camera loop + continue + + if "frame_id" in jmsg['msg']['timestamp']: + timestamps[int(jmsg['msg']['timestamp']['frame_id'])][service].append((event, time)) + continue + + if service == "pandad": + timestamps[latest_controls_frameid][service].append((event, time)) + end_times[latest_controls_frameid][service] = time + else: + frame_id = find_frame_id(time, service, start_times, end_times) + if frame_id: + if frame_id[0] != frame_id[1]: + event += " (warning: ambiguity)" + frame_id = frame_id[0] + if service == 'controlsd': + latest_controls_frameid = frame_id + timestamps[frame_id][service].append((event, time)) + else: + failed_inserts += 1 + + if latest_controls_frameid == 0: + print("Warning: failed to bind pandad logs to a frame ID. Add a timestamp cloudlog in controlsd.") + elif failed_inserts > len(timestamps): + print(f"Warning: failed to bind {failed_inserts} cloudlog timestamps to a frame ID") + +def print_timestamps(timestamps, durations, start_times, relative): + t0 = find_t0(start_times) + for frame_id in timestamps.keys(): + print('='*80) + print("Frame ID:", frame_id) + if relative: + t0 = find_t0(start_times, frame_id) + + for service in SERVICES: + print(" "+service) + events = timestamps[frame_id][service] + for event, time in sorted(events, key = lambda x: x[1]): + print(" "+f'{event:<53s}{str((time-t0)/1e6):<53s}') + for event, time in durations[frame_id][service]: + print(" "+f'{event:<53s}{str(time*1000):<53s}') + +def graph_timestamps(timestamps, start_times, end_times, relative, offset_services=False, title=""): + plt.rcParams.update({'font.size': 18}) + + t0 = find_t0(start_times) + fig, ax = plt.subplots() + ax.set_xlim(0, 130 if relative else 750) + ax.set_ylim(0, 17) + ax.set_xlabel('Time (milliseconds)') + colors = ['blue', 'green', 'red', 'yellow', 'purple'] + offsets = [[0, -5*j] for j in range(len(SERVICES))] if offset_services else None + height = 0.3 if offset_services else 0.9 + assert len(colors) == len(SERVICES), 'Each service needs a color' + + points = {"x": [], "y": [], "labels": []} + for i, (frame_id, services) in enumerate(timestamps.items()): + if relative: + t0 = find_t0(start_times, frame_id) + service_bars = [] + for service, events in services.items(): + if start_times[frame_id][service] and end_times[frame_id][service]: + start = start_times[frame_id][service] + end = end_times[frame_id][service] + service_bars.append(((start-t0)/1e6,(end-start)/1e6)) + for event in events: + points['x'].append((event[1]-t0)/1e6) + points['y'].append(i) + points['labels'].append(event[0]) + ax.broken_barh(service_bars, (i-height/2, height), facecolors=(colors), alpha=0.5, offsets=offsets) + + ax.scatter(points['x'], points['y'], marker='d', edgecolor='black') + for i, label in enumerate(points['labels']): + ax.annotate(label, (points['x'][i], points['y'][i]), textcoords="offset points", xytext=(0,10), ha='center') + + plt.title(title) + fig.set_size_inches(18, 9) + plt.legend(handles=[mpatches.Patch(color=colors[i], label=SERVICES[i]) for i in range(len(SERVICES))]) + plt.show() + +def get_timestamps(lr): + lr = list(lr) + data, frame_mismatches = read_logs(lr) + insert_cloudlogs(lr, data['timestamp'], data['start'], data['end']) + return data, frame_mismatches + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="A tool for analyzing openpilot's end-to-end latency", + formatter_class = argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--relative", action="store_true", help="Make timestamps relative to the start of each frame") + parser.add_argument("--demo", action="store_true", help="Use the demo route instead of providing one") + parser.add_argument("--plot", action="store_true", help="If a plot should be generated") + parser.add_argument("--offset", action="store_true", help="Vertically offset service to better visualize overlap") + parser.add_argument("route_or_segment_name", nargs='?', help="The route to print") + + if len(sys.argv) == 1: + parser.print_help() + sys.exit() + args = parser.parse_args() + + r = DEMO_ROUTE if args.demo else args.route_or_segment_name.strip() + lr = LogReader(r, sort_by_time=True) + + data, _ = get_timestamps(lr) + print_timestamps(data['timestamp'], data['duration'], data['start'], args.relative) + if args.plot: + graph_timestamps(data['timestamp'], data['start'], data['end'], args.relative, offset_services=args.offset, title=r) diff --git a/tools/plotjuggler/README.md b/tools/plotjuggler/README.md index 794c292e68..dc301efcb7 100644 --- a/tools/plotjuggler/README.md +++ b/tools/plotjuggler/README.md @@ -58,7 +58,7 @@ If streaming to PlotJuggler from a replay on your PC, simply run: `./juggle.py - For a quick demo, go through the installation step and run this command: -`./juggle.py --demo --layout=layouts/tuning.xml` +`./juggle.py --demo --layout=layouts/demo.xml` ## Layouts diff --git a/tools/plotjuggler/layouts/demo.xml b/tools/plotjuggler/layouts/demo.xml new file mode 100644 index 0000000000..7026221374 --- /dev/null +++ b/tools/plotjuggler/layouts/demo.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + prevX = 0 +prevY = 0 +is_first = true + if (is_first) then + is_first = false + prevX = time + prevY = value +end + +dx = time - prevX +dy = value - prevY +prevX = time +prevY = value + +return dy/dx + /carState/vEgo + + + + + + diff --git a/tools/replay/replay.cc b/tools/replay/replay.cc index a940b6d04e..2bd3614530 100644 --- a/tools/replay/replay.cc +++ b/tools/replay/replay.cc @@ -106,27 +106,31 @@ void Replay::seekTo(double seconds, bool relative) { rInfo("Seeking to %d s, segment %d", (int)target_time, target_segment); notifyEvent(onSeeking, target_time); + double seeked_to_sec = -1; interruptStream([&]() { - current_segment_.store(target_segment); + current_segment_ = target_segment; cur_mono_time_ = route_start_ts_ + target_time * 1e9; - seeking_to_.store(target_time, std::memory_order_relaxed); + seeking_to_ = target_time; + + if (event_data_->isSegmentLoaded(target_segment)) { + seeked_to_sec = *seeking_to_; + seeking_to_.reset(); + } return false; }); + checkSeekProgress(seeked_to_sec); seg_mgr_->setCurrentSegment(target_segment); - checkSeekProgress(); } -void Replay::checkSeekProgress() { - if (!seg_mgr_->getEventData()->isSegmentLoaded(current_segment_.load())) return; - - double seek_to = seeking_to_.exchange(-1.0, std::memory_order_acquire); - if (seek_to >= 0 && onSeekedTo) { - onSeekedTo(seek_to); +void Replay::checkSeekProgress(double seeked_to_sec) { + if (seeked_to_sec >= 0) { + if (onSeekedTo) { + onSeekedTo(seeked_to_sec); + } else { + interruptStream([]() { return true; }); + } } - - // Resume the interrupted stream - interruptStream([]() { return true; }); } void Replay::seekToFlag(FindFlag flag) { @@ -148,19 +152,29 @@ void Replay::pause(bool pause) { void Replay::handleSegmentMerge() { if (exit_) return; - auto event_data = seg_mgr_->getEventData(); - if (!stream_thread_.joinable() && !event_data->segments.empty()) { - startStream(event_data->segments.begin()->second); - } - notifyEvent(onSegmentsMerged); + double seeked_to_sec = -1; + interruptStream([&]() { + event_data_ = seg_mgr_->getEventData(); + notifyEvent(onSegmentsMerged); - // Interrupt the stream to handle segment merge - interruptStream([]() { return false; }); - checkSeekProgress(); + bool segment_loaded = event_data_->isSegmentLoaded(current_segment_); + if (seeking_to_ && segment_loaded) { + seeked_to_sec = *seeking_to_; + seeking_to_.reset(); + return false; + } + return segment_loaded; + }); + + checkSeekProgress(seeked_to_sec); + if (!stream_thread_.joinable() && !event_data_->events.empty()) { + startStream(); + } } -void Replay::startStream(const std::shared_ptr segment) { - const auto &events = segment->log->events; +void Replay::startStream() { + const auto &cur_segment = event_data_->segments.begin()->second; + const auto &events = cur_segment->log->events; route_start_ts_ = events.front().mono_time; cur_mono_time_ += route_start_ts_ - 1; @@ -198,7 +212,7 @@ void Replay::startStream(const std::shared_ptr segment) { if (!hasFlag(REPLAY_FLAG_NO_VIPC)) { std::pair camera_size[MAX_CAMERAS] = {}; for (auto type : ALL_CAMERAS) { - if (auto &fr = segment->frames[type]) { + if (auto &fr = cur_segment->frames[type]) { camera_size[type] = {fr->width, fr->height}; } } @@ -257,7 +271,6 @@ void Replay::streamThread() { stream_cv_.wait(lk, [this]() { return exit_ || (events_ready_ && !interrupt_requested_); }); if (exit_) break; - event_data_ = seg_mgr_->getEventData(); const auto &events = event_data_->events; auto first = std::upper_bound(events.cbegin(), events.cend(), Event(cur_which, cur_mono_time_, {})); if (first == events.cend()) { @@ -295,11 +308,11 @@ std::vector::const_iterator Replay::publishEvents(std::vector::con for (; !interrupt_requested_ && first != last; ++first) { const Event &evt = *first; - int segment = toSeconds(evt.mono_time) / 60; - if (current_segment_.load(std::memory_order_relaxed) != segment) { - current_segment_.store(segment, std::memory_order_relaxed); - seg_mgr_->setCurrentSegment(segment); + + if (current_segment_ != segment) { + current_segment_ = segment; + seg_mgr_->setCurrentSegment(current_segment_); } // Skip events if socket is not present diff --git a/tools/replay/replay.h b/tools/replay/replay.h index 8525a532a1..d549eaefc4 100644 --- a/tools/replay/replay.h +++ b/tools/replay/replay.h @@ -55,8 +55,9 @@ public: inline const std::string &carFingerprint() const { return car_fingerprint_; } inline const std::shared_ptr> getTimeline() const { return timeline_.getEntries(); } inline const std::optional findAlertAtTime(double sec) const { return timeline_.findAlertAtTime(sec); } - const std::shared_ptr getEventData() const { return seg_mgr_->getEventData(); } + const std::shared_ptr getEventData() const { return event_data_; } void installEventFilter(std::function filter) { event_filter_ = filter; } + void resumeStream() { interruptStream([]() { return true; }); } // Event callback functions std::function onSegmentsMerged = nullptr; @@ -67,7 +68,7 @@ public: private: void setupServices(const std::vector &allow, const std::vector &block); void setupSegmentManager(bool has_filters); - void startStream(const std::shared_ptr segment); + void startStream(); void streamThread(); void handleSegmentMerge(); void interruptStream(const std::function& update_fn); @@ -75,7 +76,7 @@ private: std::vector::const_iterator last); void publishMessage(const Event *e); void publishFrame(const Event *e); - void checkSeekProgress(); + void checkSeekProgress(double seeked_to_sec); std::unique_ptr seg_mgr_; Timeline timeline_; @@ -85,8 +86,8 @@ private: std::mutex stream_lock_; bool user_paused_ = false; std::condition_variable stream_cv_; - std::atomic current_segment_ = 0; - std::atomic seeking_to_ = -1.0; + int current_segment_ = 0; + std::optional seeking_to_; std::atomic exit_ = false; std::atomic interrupt_requested_ = false; bool events_ready_ = false; diff --git a/tools/replay/seg_mgr.cc b/tools/replay/seg_mgr.cc index 8a00d426b1..954b25e874 100644 --- a/tools/replay/seg_mgr.cc +++ b/tools/replay/seg_mgr.cc @@ -105,7 +105,7 @@ bool SegmentManager::mergeSegments(const SegmentMap::iterator &begin, const Segm merged_event_data->segments[n] = segments_.at(n); } - std::atomic_store(&event_data_, std::move(merged_event_data)); + event_data_ = merged_event_data; merged_segments_ = segments_to_merge; return true; diff --git a/tools/replay/seg_mgr.h b/tools/replay/seg_mgr.h index 40bdcd51f0..efb3d7f0ea 100644 --- a/tools/replay/seg_mgr.h +++ b/tools/replay/seg_mgr.h @@ -21,14 +21,14 @@ public: }; SegmentManager(const std::string &route_name, uint32_t flags, const std::string &data_dir = "") - : flags_(flags), route_(route_name, data_dir), event_data_(std::make_shared()) {} + : flags_(flags), route_(route_name, data_dir) {}; ~SegmentManager(); bool load(); void setCurrentSegment(int seg_num); void setCallback(const std::function &callback) { onSegmentMergedCallback_ = callback; } void setFilters(const std::vector &filters) { filters_ = filters; } - const std::shared_ptr getEventData() const { return std::atomic_load(&event_data_); } + const std::shared_ptr getEventData() const { return event_data_; } bool hasSegment(int n) const { return segments_.find(n) != segments_.end(); } Route route_; diff --git a/tools/replay/timeline.cc b/tools/replay/timeline.cc index a4c2ffb700..d836de972b 100644 --- a/tools/replay/timeline.cc +++ b/tools/replay/timeline.cc @@ -1,7 +1,7 @@ #include "tools/replay/timeline.h" -#include #include +#include #include "cereal/gen/cpp/log.capnp.h" @@ -74,7 +74,7 @@ void Timeline::buildTimeline(const Route &route, uint64_t route_start_ts, bool l // Sort and finalize the timeline entries auto entries = std::make_shared>(staging_entries_); std::sort(entries->begin(), entries->end(), [](auto &a, auto &b) { return a.start_time < b.start_time; }); - std::atomic_store(&timeline_entries_, std::move(entries)); + timeline_entries_ = entries; callback(log); // Notify the callback once the log is processed } diff --git a/tools/replay/timeline.h b/tools/replay/timeline.h index 74add9e5cc..689a80635f 100644 --- a/tools/replay/timeline.h +++ b/tools/replay/timeline.h @@ -27,20 +27,20 @@ public: std::function)> callback); std::optional find(double cur_ts, FindFlag flag) const; std::optional findAlertAtTime(double target_time) const; - const std::shared_ptr> getEntries() const { return std::atomic_load(&timeline_entries_); } + const std::shared_ptr> getEntries() const { return timeline_entries_; } private: - void buildTimeline(const Route &route, uint64_t route_start_ts, bool local_cache, - std::function)> callback); - void updateEngagementStatus(const cereal::SelfdriveState::Reader &cs, std::optional &idx, double seconds); - void updateAlertStatus(const cereal::SelfdriveState::Reader &cs, std::optional &idx, double seconds); + void buildTimeline(const Route &route, uint64_t route_start_ts, bool local_cache, + std::function)> callback); + void updateEngagementStatus(const cereal::SelfdriveState::Reader &cs, std::optional &idx, double seconds); + void updateAlertStatus(const cereal::SelfdriveState::Reader &cs, std::optional &idx, double seconds); - std::thread thread_; - std::atomic should_exit_ = false; + std::thread thread_; + std::atomic should_exit_ = false; - // Temporarily holds entries before they are sorted and finalized - std::vector staging_entries_; + // Temporarily holds entries before they are sorted and finalized + std::vector staging_entries_; - // Final sorted timeline entries - std::shared_ptr> timeline_entries_; + // Final sorted timeline entries + std::shared_ptr> timeline_entries_; }; diff --git a/tools/rerun/README.md b/tools/rerun/README.md index 11a8d33ee1..dc0a901e60 100644 --- a/tools/rerun/README.md +++ b/tools/rerun/README.md @@ -24,14 +24,14 @@ options: Examples using route name to observe accelerometer and qcamera: -`./run.py --qcam "a2a0ccea32023010/2023-07-27--13-01-19"` +`./run.sh --qcam "a2a0ccea32023010/2023-07-27--13-01-19"` Examples using segment range (more on [SegmentRange](https://github.com/commaai/openpilot/tree/master/tools/lib)): -`./run.py --qcam "a2a0ccea32023010/2023-07-27--13-01-19/2:4"` +`./run.sh --qcam "a2a0ccea32023010/2023-07-27--13-01-19/2:4"` ## Cautions: - Showing hevc videos (`--fcam`, `--ecam`, and `--dcam`) are expensive, and it's recommended to use `--qcam` for optimized performance. If possible, limiting your route to a few segments using `SegmentRange` will speed up logging and reduce memory usage ## Demo -`./run.py --qcam --demo` +`./run.sh --qcam --demo` diff --git a/tools/rerun/run.sh b/tools/rerun/run.sh new file mode 100755 index 0000000000..0c02615360 --- /dev/null +++ b/tools/rerun/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# TODO: remove this file once Rerun has interface to set log message level +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +RUST_LOG=warn $DIR/run.py $@ + diff --git a/tools/webcam/README.md b/tools/webcam/README.md index f4b46d1f66..c756069bb5 100644 --- a/tools/webcam/README.md +++ b/tools/webcam/README.md @@ -1,7 +1,7 @@ # Run openpilot with webcam on PC What's needed: -- Ubuntu 24.04 ([WSL2 is not supported](https://github.com/commaai/openpilot/issues/34216)) +- Ubuntu 24.04 - GPU (recommended) - Two USB webcams, at least 720p and 78 degrees FOV (e.g. Logitech C920/C615) - [Car harness](https://comma.ai/shop/products/comma-car-harness) with black panda to connect to your car @@ -9,27 +9,29 @@ What's needed: That's it! ## Setup openpilot -- Follow [this readme](../README.md) to install and build the requirements -- Install OpenCL Driver ``` -sudo apt install pocl-opencl-icd +cd ~ +git clone https://github.com/commaai/openpilot.git +``` +- Follow [this readme](https://github.com/commaai/openpilot/tree/master/tools) to install the requirements +- Install [OpenCL Driver](https://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/15532/l_opencl_p_18.1.0.015.tgz) + +## Build openpilot for webcam +``` +cd ~/openpilot +USE_WEBCAM=1 scons -j$(nproc) ``` ## Connect the hardware - Connect the road facing camera first, then the driver facing camera +- (default indexes are 1 and 2; can be modified in system/camerad/cameras/camera_webcam.cc) - Connect your computer to panda ## GO ``` -USE_WEBCAM=1 system/manager/manager.py +cd ~/openpilot/system/manager +NOSENSOR=1 USE_WEBCAM=1 ./manager.py ``` - Start the car, then the UI should show the road webcam's view -- Adjust and secure the webcams. +- Adjust and secure the webcams (you can run tools/webcam/front_mount_helper.py to help mount the driver camera) - Finish calibration and engage! - -## Specify Cameras - -Use the `ROAD_CAM`, `DRIVER_CAM`, and optional `WIDE_CAM` environment variables to specify which camera is which (ie. `DRIVER_CAM=2` uses `/dev/video2` for the driver-facing camera): -``` -USE_WEBCAM=1 ROAD_CAM=4 WIDE_CAM=6 system/manager/manager.py -``` diff --git a/tools/webcam/camerad.py b/tools/webcam/camerad.py index a0916ed5ee..778fefb834 100755 --- a/tools/webcam/camerad.py +++ b/tools/webcam/camerad.py @@ -9,14 +9,14 @@ from cereal import messaging from openpilot.tools.webcam.camera import Camera from openpilot.common.realtime import Ratekeeper -WIDE_CAM = os.getenv("WIDE_CAM") +DUAL_CAM = os.getenv("DUAL_CAMERA") CameraType = namedtuple("CameraType", ["msg_name", "stream_type", "cam_id"]) CAMERAS = [ - CameraType("roadCameraState", VisionStreamType.VISION_STREAM_ROAD, os.getenv("ROAD_CAM", "0")), - CameraType("driverCameraState", VisionStreamType.VISION_STREAM_DRIVER, os.getenv("DRIVER_CAM", "2")), + CameraType("roadCameraState", VisionStreamType.VISION_STREAM_ROAD, os.getenv("CAMERA_ROAD_ID", "/dev/video0")), + CameraType("driverCameraState", VisionStreamType.VISION_STREAM_DRIVER, os.getenv("CAMERA_DRIVER_ID", "/dev/video1")), ] -if WIDE_CAM: - CAMERAS.append(CameraType("wideRoadCameraState", VisionStreamType.VISION_STREAM_WIDE_ROAD, WIDE_CAM)) +if DUAL_CAM: + CAMERAS.append(CameraType("wideRoadCameraState", VisionStreamType.VISION_STREAM_WIDE_ROAD, DUAL_CAM)) class Camerad: def __init__(self): @@ -25,9 +25,8 @@ class Camerad: self.cameras = [] for c in CAMERAS: - cam_device = f"/dev/video{c.cam_id}" - print(f"opening {c.msg_name} at {cam_device}") - cam = Camera(c.msg_name, c.stream_type, cam_device) + print(f"opening {c.msg_name} at {c.cam_id}") + cam = Camera(c.msg_name, c.stream_type, c.cam_id) self.cameras.append(cam) self.vipc_server.create_buffers(c.stream_type, 20, cam.W, cam.H) diff --git a/tools/webcam/start_camerad.sh b/tools/webcam/start_camerad.sh new file mode 100755 index 0000000000..aefc4c062a --- /dev/null +++ b/tools/webcam/start_camerad.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# export the block below when call manager.py +export BLOCK="${BLOCK},camerad" +export USE_WEBCAM="1" + +# Change camera index according to your setting +export CAMERA_ROAD_ID="/dev/video0" +export CAMERA_DRIVER_ID="/dev/video1" +#export DUAL_CAMERA="/dev/video2" # optional, camera index for wide road camera + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +$DIR/camerad.py diff --git a/uv.lock b/uv.lock index e25fd79c42..f1a5fa9915 100644 --- a/uv.lock +++ b/uv.lock @@ -1,12 +1,12 @@ version = 1 requires-python = ">=3.11, <3.13" resolution-markers = [ - "python_full_version >= '3.12' and sys_platform == 'darwin'", - "python_full_version >= '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform != 'darwin' and sys_platform != 'linux')", - "python_full_version < '3.12' and sys_platform == 'darwin'", - "python_full_version < '3.12' and platform_machine == 'aarch64' and sys_platform == 'linux'", - "(python_full_version < '3.12' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version < '3.12' and sys_platform != 'darwin' and sys_platform != 'linux')", + "python_full_version < '3.12' and platform_system == 'Darwin'", + "python_full_version < '3.12' and platform_machine == 'aarch64' and platform_system == 'Linux'", + "(python_full_version < '3.12' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version < '3.12' and platform_system != 'Darwin' and platform_system != 'Linux')", + "python_full_version >= '3.12' and platform_system == 'Darwin'", + "python_full_version >= '3.12' and platform_machine == 'aarch64' and platform_system == 'Linux'", + "(python_full_version >= '3.12' and platform_machine != 'aarch64' and platform_system == 'Linux') or (python_full_version >= '3.12' and platform_system != 'Darwin' and platform_system != 'Linux')", ] [[package]] @@ -20,7 +20,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.11.11" +version = "3.11.10" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -31,38 +31,38 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618 } +sdist = { url = "https://files.pythonhosted.org/packages/94/c4/3b5a937b16f6c2a0ada842a9066aad0b7a5708427d4a202a07bf09c67cbb/aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e", size = 7668832 } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624 }, - { url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507 }, - { url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571 }, - { url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694 }, - { url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660 }, - { url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421 }, - { url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145 }, - { url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804 }, - { url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007 }, - { url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022 }, - { url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899 }, - { url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142 }, - { url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736 }, - { url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418 }, - { url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509 }, - { url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666 }, - { url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057 }, - { url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996 }, - { url = "https://files.pythonhosted.org/packages/b7/dd/485061fbfef33165ce7320db36e530cd7116ee1098e9c3774d15a732b3fd/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", size = 1682367 }, - { url = "https://files.pythonhosted.org/packages/e9/d7/9ec5b3ea9ae215c311d88b2093e8da17e67b8856673e4166c994e117ee3e/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", size = 1736989 }, - { url = "https://files.pythonhosted.org/packages/d6/fb/ea94927f7bfe1d86178c9d3e0a8c54f651a0a655214cce930b3c679b8f64/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e", size = 1793265 }, - { url = "https://files.pythonhosted.org/packages/40/7f/6de218084f9b653026bd7063cd8045123a7ba90c25176465f266976d8c82/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", size = 1691841 }, - { url = "https://files.pythonhosted.org/packages/77/e2/992f43d87831cbddb6b09c57ab55499332f60ad6fdbf438ff4419c2925fc/aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", size = 1619317 }, - { url = "https://files.pythonhosted.org/packages/96/74/879b23cdd816db4133325a201287c95bef4ce669acde37f8f1b8669e1755/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", size = 1641416 }, - { url = "https://files.pythonhosted.org/packages/30/98/b123f6b15d87c54e58fd7ae3558ff594f898d7f30a90899718f3215ad328/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", size = 1646514 }, - { url = "https://files.pythonhosted.org/packages/d7/38/257fda3dc99d6978ab943141d5165ec74fd4b4164baa15e9c66fa21da86b/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", size = 1702095 }, - { url = "https://files.pythonhosted.org/packages/0c/f4/ddab089053f9fb96654df5505c0a69bde093214b3c3454f6bfdb1845f558/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", size = 1734611 }, - { url = "https://files.pythonhosted.org/packages/c3/d6/f30b2bc520c38c8aa4657ed953186e535ae84abe55c08d0f70acd72ff577/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", size = 1694576 }, - { url = "https://files.pythonhosted.org/packages/bc/97/b0a88c3f4c6d0020b34045ee6d954058abc870814f6e310c4c9b74254116/aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", size = 411363 }, - { url = "https://files.pythonhosted.org/packages/7f/23/cc36d9c398980acaeeb443100f0216f50a7cfe20c67a9fd0a2f1a5a846de/aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", size = 437666 }, + { url = "https://files.pythonhosted.org/packages/db/7c/584d5ca19343c9462d054337828f72628e6dc204424f525df59ebfe75d1e/aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b", size = 708395 }, + { url = "https://files.pythonhosted.org/packages/cd/2d/61c33e01baeb23aebd07620ee4d780ff40f4c17c42289bf02a405f2ac312/aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1", size = 468281 }, + { url = "https://files.pythonhosted.org/packages/ab/70/0ddb3a61b835068eb0badbe8016b4b65b966bad5f8af0f2d63998ff4cfa4/aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683", size = 455345 }, + { url = "https://files.pythonhosted.org/packages/44/8c/4e14e9c1767d9a6ab1af1fbad9df9c77e050b39b6afe9e8343ec1ba96508/aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d", size = 1685464 }, + { url = "https://files.pythonhosted.org/packages/ef/6e/1bab78ebb4f5a1c54f0fc10f8d52abc06816a9cb1db52b9c908e3d69f9a8/aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299", size = 1743427 }, + { url = "https://files.pythonhosted.org/packages/5d/5e/c1b03bef621a8cc51ff551ef223c6ac606fabe0e35c950f56d01423ec2aa/aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8", size = 1785188 }, + { url = "https://files.pythonhosted.org/packages/7c/b8/df6d76a149cbd969a58da478baec0be617287c496c842ddf21fe6bce07b3/aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0", size = 1674911 }, + { url = "https://files.pythonhosted.org/packages/ee/8e/e460e7bb820a08cec399971fc3176afc8090dc32fb941f386e0c68bc4ecc/aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5", size = 1619570 }, + { url = "https://files.pythonhosted.org/packages/c2/ae/3b597e09eae4e75b77ee6c65443593d245bfa067ae6a5d895abaf27cce6c/aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46", size = 1653772 }, + { url = "https://files.pythonhosted.org/packages/b8/d1/99852f2925992c4d7004e590344e5398eb163750de2a7c1fbe07f182d3c8/aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838", size = 1649787 }, + { url = "https://files.pythonhosted.org/packages/39/c0/ea24627e08d722d5a6a00b3f6c9763fe3ad4650b8485f7a7a56ff932e3af/aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b", size = 1732666 }, + { url = "https://files.pythonhosted.org/packages/f1/27/ab52dee4443ef8bdb26473b53c841caafd2bb637a8d85751694e089913bb/aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52", size = 1754910 }, + { url = "https://files.pythonhosted.org/packages/cd/08/57c919d6b1f3b70bc14433c080a6152bf99454b636eb8a88552de8baaca9/aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3", size = 1692502 }, + { url = "https://files.pythonhosted.org/packages/ae/37/015006f669275735049e0549c37cb79c7a4a9350cbee070bbccb5a5b4b8a/aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4", size = 416178 }, + { url = "https://files.pythonhosted.org/packages/cf/8d/7bb48ae503989b15114baf9f9b19398c86ae93d30959065bc061b31331ee/aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec", size = 442269 }, + { url = "https://files.pythonhosted.org/packages/25/17/1dbe2f619f77795409c1a13ab395b98ed1b215d3e938cacde9b8ffdac53d/aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf", size = 704448 }, + { url = "https://files.pythonhosted.org/packages/e3/9b/112247ad47e9d7f6640889c6e42cc0ded8c8345dd0033c66bcede799b051/aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138", size = 463829 }, + { url = "https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5", size = 455774 }, + { url = "https://files.pythonhosted.org/packages/e5/75/ee1b8f510978b3de5f185c62535b135e4fc3f5a247ca0c2245137a02d800/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50", size = 1682134 }, + { url = "https://files.pythonhosted.org/packages/87/46/65e8259432d5f73ca9ebf5edb645ef90e5303724e4e52477516cb4042240/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c", size = 1736757 }, + { url = "https://files.pythonhosted.org/packages/03/f6/a6d1e791b7153fb2d101278f7146c0771b0e1569c547f8a8bc3035651984/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d", size = 1793033 }, + { url = "https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b", size = 1691609 }, + { url = "https://files.pythonhosted.org/packages/6d/a6/77b33da5a0bc04566c7ddcca94500f2c2a2334eecab4885387fffd1fc600/aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109", size = 1619082 }, + { url = "https://files.pythonhosted.org/packages/48/94/5bf5f927d9a2fedd2c978adfb70a3680e16f46d178361685b56244eb52ed/aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab", size = 1641186 }, + { url = "https://files.pythonhosted.org/packages/99/2d/e85103aa01d1064e51bc50cb51e7b40150a8ff5d34e5a3173a46b241860b/aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69", size = 1646280 }, + { url = "https://files.pythonhosted.org/packages/7b/e0/44651fda8c1d865a51b3a81f1956ea55ce16fc568fe7a3e05db7fc22f139/aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0", size = 1701862 }, + { url = "https://files.pythonhosted.org/packages/4e/1e/0804459ae325a5b95f6f349778fb465f29d2b863e522b6a349db0aaad54c/aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9", size = 1734373 }, + { url = "https://files.pythonhosted.org/packages/07/87/b8f6721668cad74bcc9c7cfe6d0230b304d1250196b221e54294a0d78dbe/aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc", size = 1694343 }, + { url = "https://files.pythonhosted.org/packages/4b/20/42813fc60d9178ba9b1b86c58a5441ddb6cf8ffdfe66387345bff173bcff/aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985", size = 411118 }, + { url = "https://files.pythonhosted.org/packages/3a/51/df9c263c861ce93998b5ad2ba3212caab2112d5b66dbe91ddbe90c41ded4/aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408", size = 437424 }, ] [[package]] @@ -257,49 +257,53 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.1" +version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", size = 106620 } wheels = [ - { url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 }, - { url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 }, - { url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 }, - { url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 }, - { url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 }, - { url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 }, - { url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 }, - { url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 }, - { url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 }, - { url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 }, - { url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 }, - { url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 }, - { url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 }, - { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, - { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, - { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, - { url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 }, - { url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 }, - { url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 }, - { url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 }, - { url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 }, - { url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 }, - { url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 }, - { url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 }, - { url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 }, - { url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 }, - { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, + { url = "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", size = 193339 }, + { url = "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", size = 124366 }, + { url = "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", size = 118874 }, + { url = "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", size = 138243 }, + { url = "https://files.pythonhosted.org/packages/e2/29/d227805bff72ed6d6cb1ce08eec707f7cfbd9868044893617eb331f16295/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", size = 148676 }, + { url = "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", size = 141289 }, + { url = "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", size = 142585 }, + { url = "https://files.pythonhosted.org/packages/3b/a0/a68980ab8a1f45a36d9745d35049c1af57d27255eff8c907e3add84cf68f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", size = 144408 }, + { url = "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", size = 139076 }, + { url = "https://files.pythonhosted.org/packages/fb/9d/9c13753a5a6e0db4a0a6edb1cef7aee39859177b64e1a1e748a6e3ba62c2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", size = 146874 }, + { url = "https://files.pythonhosted.org/packages/75/d2/0ab54463d3410709c09266dfb416d032a08f97fd7d60e94b8c6ef54ae14b/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", size = 150871 }, + { url = "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", size = 148546 }, + { url = "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", size = 143048 }, + { url = "https://files.pythonhosted.org/packages/01/f8/38842422988b795220eb8038745d27a675ce066e2ada79516c118f291f07/charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", size = 94389 }, + { url = "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", size = 101752 }, + { url = "https://files.pythonhosted.org/packages/d3/0b/4b7a70987abf9b8196845806198975b6aab4ce016632f817ad758a5aa056/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", size = 194445 }, + { url = "https://files.pythonhosted.org/packages/50/89/354cc56cf4dd2449715bc9a0f54f3aef3dc700d2d62d1fa5bbea53b13426/charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", size = 125275 }, + { url = "https://files.pythonhosted.org/packages/fa/44/b730e2a2580110ced837ac083d8ad222343c96bb6b66e9e4e706e4d0b6df/charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", size = 119020 }, + { url = "https://files.pythonhosted.org/packages/9d/e4/9263b8240ed9472a2ae7ddc3e516e71ef46617fe40eaa51221ccd4ad9a27/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", size = 139128 }, + { url = "https://files.pythonhosted.org/packages/6b/e3/9f73e779315a54334240353eaea75854a9a690f3f580e4bd85d977cb2204/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", size = 149277 }, + { url = "https://files.pythonhosted.org/packages/1a/cf/f1f50c2f295312edb8a548d3fa56a5c923b146cd3f24114d5adb7e7be558/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", size = 142174 }, + { url = "https://files.pythonhosted.org/packages/16/92/92a76dc2ff3a12e69ba94e7e05168d37d0345fa08c87e1fe24d0c2a42223/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", size = 143838 }, + { url = "https://files.pythonhosted.org/packages/a4/01/2117ff2b1dfc61695daf2babe4a874bca328489afa85952440b59819e9d7/charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", size = 146149 }, + { url = "https://files.pythonhosted.org/packages/f6/9b/93a332b8d25b347f6839ca0a61b7f0287b0930216994e8bf67a75d050255/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", size = 140043 }, + { url = "https://files.pythonhosted.org/packages/ab/f6/7ac4a01adcdecbc7a7587767c776d53d369b8b971382b91211489535acf0/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", size = 148229 }, + { url = "https://files.pythonhosted.org/packages/9d/be/5708ad18161dee7dc6a0f7e6cf3a88ea6279c3e8484844c0590e50e803ef/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", size = 151556 }, + { url = "https://files.pythonhosted.org/packages/5a/bb/3d8bc22bacb9eb89785e83e6723f9888265f3a0de3b9ce724d66bd49884e/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", size = 149772 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/d3fc622de05a86f30beea5fc4e9ac46aead4731e73fd9055496732bcc0a4/charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", size = 144800 }, + { url = "https://files.pythonhosted.org/packages/9a/65/bdb9bc496d7d190d725e96816e20e2ae3a6fa42a5cac99c3c3d6ff884118/charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", size = 94836 }, + { url = "https://files.pythonhosted.org/packages/3e/67/7b72b69d25b89c0b3cea583ee372c43aa24df15f0e0f8d3982c57804984b/charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", size = 102187 }, + { url = "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", size = 49446 }, ] [[package]] name = "click" -version = "8.1.8" +version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, ] [[package]] @@ -374,30 +378,30 @@ wheels = [ [[package]] name = "coverage" -version = "7.6.10" +version = "7.6.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } +sdist = { url = "https://files.pythonhosted.org/packages/5b/d2/c25011f4d036cf7e8acbbee07a8e09e9018390aee25ba085596c4b83d510/coverage-7.6.9.tar.gz", hash = "sha256:4a8d8977b0c6ef5aeadcb644da9e69ae0dcfe66ec7f368c89c72e058bd71164d", size = 801710 } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, - { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, - { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, - { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, - { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, - { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, - { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, - { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, - { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, - { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, - { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, - { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, - { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, - { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, - { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, - { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, - { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, - { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, - { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, - { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, + { url = "https://files.pythonhosted.org/packages/b1/91/b3dc2f7f38b5cca1236ab6bbb03e84046dd887707b4ec1db2baa47493b3b/coverage-7.6.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:932fc826442132dde42ee52cf66d941f581c685a6313feebed358411238f60f9", size = 207133 }, + { url = "https://files.pythonhosted.org/packages/0d/2b/53fd6cb34d443429a92b3ec737f4953627e38b3bee2a67a3c03425ba8573/coverage-7.6.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:085161be5f3b30fd9b3e7b9a8c301f935c8313dcf928a07b116324abea2c1c2c", size = 207577 }, + { url = "https://files.pythonhosted.org/packages/74/f2/68edb1e6826f980a124f21ea5be0d324180bf11de6fd1defcf9604f76df0/coverage-7.6.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccc660a77e1c2bf24ddbce969af9447a9474790160cfb23de6be4fa88e3951c7", size = 239524 }, + { url = "https://files.pythonhosted.org/packages/d3/83/8fec0ee68c2c4a5ab5f0f8527277f84ed6f2bd1310ae8a19d0c5532253ab/coverage-7.6.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c69e42c892c018cd3c8d90da61d845f50a8243062b19d228189b0224150018a9", size = 236925 }, + { url = "https://files.pythonhosted.org/packages/8b/20/8f50e7c7ad271144afbc2c1c6ec5541a8c81773f59352f8db544cad1a0ec/coverage-7.6.9-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0824a28ec542a0be22f60c6ac36d679e0e262e5353203bea81d44ee81fe9c6d4", size = 238792 }, + { url = "https://files.pythonhosted.org/packages/6f/62/4ac2e5ad9e7a5c9ec351f38947528e11541f1f00e8a0cdce56f1ba7ae301/coverage-7.6.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4401ae5fc52ad8d26d2a5d8a7428b0f0c72431683f8e63e42e70606374c311a1", size = 237682 }, + { url = "https://files.pythonhosted.org/packages/58/2f/9d2203f012f3b0533c73336c74134b608742be1ce475a5c72012573cfbb4/coverage-7.6.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:98caba4476a6c8d59ec1eb00c7dd862ba9beca34085642d46ed503cc2d440d4b", size = 236310 }, + { url = "https://files.pythonhosted.org/packages/33/6d/31f6ab0b4f0f781636075f757eb02141ea1b34466d9d1526dbc586ed7078/coverage-7.6.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ee5defd1733fd6ec08b168bd4f5387d5b322f45ca9e0e6c817ea6c4cd36313e3", size = 237096 }, + { url = "https://files.pythonhosted.org/packages/7d/fb/e14c38adebbda9ed8b5f7f8e03340ac05d68d27b24397f8d47478927a333/coverage-7.6.9-cp311-cp311-win32.whl", hash = "sha256:f2d1ec60d6d256bdf298cb86b78dd715980828f50c46701abc3b0a2b3f8a0dc0", size = 209682 }, + { url = "https://files.pythonhosted.org/packages/a4/11/a782af39b019066af83fdc0e8825faaccbe9d7b19a803ddb753114b429cc/coverage-7.6.9-cp311-cp311-win_amd64.whl", hash = "sha256:0d59fd927b1f04de57a2ba0137166d31c1a6dd9e764ad4af552912d70428c92b", size = 210542 }, + { url = "https://files.pythonhosted.org/packages/60/52/b16af8989a2daf0f80a88522bd8e8eed90b5fcbdecf02a6888f3e80f6ba7/coverage-7.6.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:99e266ae0b5d15f1ca8d278a668df6f51cc4b854513daab5cae695ed7b721cf8", size = 207325 }, + { url = "https://files.pythonhosted.org/packages/0f/79/6b7826fca8846c1216a113227b9f114ac3e6eacf168b4adcad0cb974aaca/coverage-7.6.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9901d36492009a0a9b94b20e52ebfc8453bf49bb2b27bca2c9706f8b4f5a554a", size = 207563 }, + { url = "https://files.pythonhosted.org/packages/a7/07/0bc73da0ccaf45d0d64ef86d33b7d7fdeef84b4c44bf6b85fb12c215c5a6/coverage-7.6.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abd3e72dd5b97e3af4246cdada7738ef0e608168de952b837b8dd7e90341f015", size = 240580 }, + { url = "https://files.pythonhosted.org/packages/71/8a/9761f409910961647d892454687cedbaccb99aae828f49486734a82ede6e/coverage-7.6.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff74026a461eb0660366fb01c650c1d00f833a086b336bdad7ab00cc952072b3", size = 237613 }, + { url = "https://files.pythonhosted.org/packages/8b/10/ee7d696a17ac94f32f2dbda1e17e730bf798ae9931aec1fc01c1944cd4de/coverage-7.6.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65dad5a248823a4996724a88eb51d4b31587aa7aa428562dbe459c684e5787ae", size = 239684 }, + { url = "https://files.pythonhosted.org/packages/16/60/aa1066040d3c52fff051243c2d6ccda264da72dc6d199d047624d395b2b2/coverage-7.6.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:22be16571504c9ccea919fcedb459d5ab20d41172056206eb2994e2ff06118a4", size = 239112 }, + { url = "https://files.pythonhosted.org/packages/4e/e5/69f35344c6f932ba9028bf168d14a79fedb0dd4849b796d43c81ce75a3c9/coverage-7.6.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f957943bc718b87144ecaee70762bc2bc3f1a7a53c7b861103546d3a403f0a6", size = 237428 }, + { url = "https://files.pythonhosted.org/packages/32/20/adc895523c4a28f63441b8ac645abd74f9bdd499d2d175bef5b41fc7f92d/coverage-7.6.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ae1387db4aecb1f485fb70a6c0148c6cdaebb6038f1d40089b1fc84a5db556f", size = 239098 }, + { url = "https://files.pythonhosted.org/packages/a9/a6/e0e74230c9bb3549ec8ffc137cfd16ea5d56e993d6bffed2218bff6187e3/coverage-7.6.9-cp312-cp312-win32.whl", hash = "sha256:1a330812d9cc7ac2182586f6d41b4d0fadf9be9049f350e0efb275c8ee8eb692", size = 209940 }, + { url = "https://files.pythonhosted.org/packages/3e/18/cb5b88349d4aa2f41ec78d65f92ea32572b30b3f55bc2b70e87578b8f434/coverage-7.6.9-cp312-cp312-win_amd64.whl", hash = "sha256:b12c6b18269ca471eedd41c1b6a1065b2f7827508edb9a7ed5555e9a56dcfc97", size = 210726 }, ] [package.optional-dependencies] @@ -497,7 +501,7 @@ name = "ewmhlib" version = "0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-xlib", marker = "sys_platform == 'linux'" }, + { name = "python-xlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, { name = "typing-extensions" }, ] wheels = [ @@ -533,11 +537,11 @@ wheels = [ [[package]] name = "flatbuffers" -version = "24.12.23" +version = "24.3.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a3/83/9ae01534f7e92a0c04f86586a0d62a4a0266e51d8bb2bfd5b8ea8165abba/flatbuffers-24.12.23.tar.gz", hash = "sha256:2910b0bc6ae9b6db78dd2b18d0b7a0709ba240fb5585f286a3a2b30785c22dac", size = 22164 } +sdist = { url = "https://files.pythonhosted.org/packages/a9/74/2df95ef84b214d2bee0886d572775a6f38793f5ca6d7630c3239c91104ac/flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4", size = 22139 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/b4/31c461eef98b96b8ab736d97274548eaf2b2e349bf09e4de3902f7d53084/flatbuffers-24.12.23-py2.py3-none-any.whl", hash = "sha256:c418e0d48890f4142b92fd3e343e73a48f194e1f80075ddcc5793779b3585444", size = 30962 }, + { url = "https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812", size = 26784 }, ] [[package]] @@ -663,7 +667,7 @@ name = "humanfriendly" version = "10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pyreadline3", marker = "sys_platform == 'win32'" }, + { name = "pyreadline3", marker = "(platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 } wheels = [ @@ -730,14 +734,14 @@ wheels = [ [[package]] name = "jinja2" -version = "3.1.5" +version = "3.1.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 } +sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 }, + { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, ] [[package]] @@ -751,51 +755,53 @@ wheels = [ [[package]] name = "kiwisolver" -version = "1.4.8" +version = "1.4.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538 } +sdist = { url = "https://files.pythonhosted.org/packages/85/4d/2255e1c76304cbd60b48cee302b66d1dde4468dc5b1160e4b7cb43778f2a/kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60", size = 97286 } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/ed/c913ee28936c371418cb167b128066ffb20bbf37771eecc2c97edf8a6e4c/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84", size = 124635 }, - { url = "https://files.pythonhosted.org/packages/4c/45/4a7f896f7467aaf5f56ef093d1f329346f3b594e77c6a3c327b2d415f521/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561", size = 66717 }, - { url = "https://files.pythonhosted.org/packages/5f/b4/c12b3ac0852a3a68f94598d4c8d569f55361beef6159dce4e7b624160da2/kiwisolver-1.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7", size = 65413 }, - { url = "https://files.pythonhosted.org/packages/a9/98/1df4089b1ed23d83d410adfdc5947245c753bddfbe06541c4aae330e9e70/kiwisolver-1.4.8-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03", size = 1343994 }, - { url = "https://files.pythonhosted.org/packages/8d/bf/b4b169b050c8421a7c53ea1ea74e4ef9c335ee9013216c558a047f162d20/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954", size = 1434804 }, - { url = "https://files.pythonhosted.org/packages/66/5a/e13bd341fbcf73325ea60fdc8af752addf75c5079867af2e04cc41f34434/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79", size = 1450690 }, - { url = "https://files.pythonhosted.org/packages/9b/4f/5955dcb376ba4a830384cc6fab7d7547bd6759fe75a09564910e9e3bb8ea/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6", size = 1376839 }, - { url = "https://files.pythonhosted.org/packages/3a/97/5edbed69a9d0caa2e4aa616ae7df8127e10f6586940aa683a496c2c280b9/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0", size = 1435109 }, - { url = "https://files.pythonhosted.org/packages/13/fc/e756382cb64e556af6c1809a1bbb22c141bbc2445049f2da06b420fe52bf/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab", size = 2245269 }, - { url = "https://files.pythonhosted.org/packages/76/15/e59e45829d7f41c776d138245cabae6515cb4eb44b418f6d4109c478b481/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc", size = 2393468 }, - { url = "https://files.pythonhosted.org/packages/e9/39/483558c2a913ab8384d6e4b66a932406f87c95a6080112433da5ed668559/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25", size = 2355394 }, - { url = "https://files.pythonhosted.org/packages/01/aa/efad1fbca6570a161d29224f14b082960c7e08268a133fe5dc0f6906820e/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc", size = 2490901 }, - { url = "https://files.pythonhosted.org/packages/c9/4f/15988966ba46bcd5ab9d0c8296914436720dd67fca689ae1a75b4ec1c72f/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67", size = 2312306 }, - { url = "https://files.pythonhosted.org/packages/2d/27/bdf1c769c83f74d98cbc34483a972f221440703054894a37d174fba8aa68/kiwisolver-1.4.8-cp311-cp311-win_amd64.whl", hash = "sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34", size = 71966 }, - { url = "https://files.pythonhosted.org/packages/4a/c9/9642ea855604aeb2968a8e145fc662edf61db7632ad2e4fb92424be6b6c0/kiwisolver-1.4.8-cp311-cp311-win_arm64.whl", hash = "sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2", size = 65311 }, - { url = "https://files.pythonhosted.org/packages/fc/aa/cea685c4ab647f349c3bc92d2daf7ae34c8e8cf405a6dcd3a497f58a2ac3/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502", size = 124152 }, - { url = "https://files.pythonhosted.org/packages/c5/0b/8db6d2e2452d60d5ebc4ce4b204feeb16176a851fd42462f66ade6808084/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31", size = 66555 }, - { url = "https://files.pythonhosted.org/packages/60/26/d6a0db6785dd35d3ba5bf2b2df0aedc5af089962c6eb2cbf67a15b81369e/kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb", size = 65067 }, - { url = "https://files.pythonhosted.org/packages/c9/ed/1d97f7e3561e09757a196231edccc1bcf59d55ddccefa2afc9c615abd8e0/kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f", size = 1378443 }, - { url = "https://files.pythonhosted.org/packages/29/61/39d30b99954e6b46f760e6289c12fede2ab96a254c443639052d1b573fbc/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc", size = 1472728 }, - { url = "https://files.pythonhosted.org/packages/0c/3e/804163b932f7603ef256e4a715e5843a9600802bb23a68b4e08c8c0ff61d/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a", size = 1478388 }, - { url = "https://files.pythonhosted.org/packages/8a/9e/60eaa75169a154700be74f875a4d9961b11ba048bef315fbe89cb6999056/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a", size = 1413849 }, - { url = "https://files.pythonhosted.org/packages/bc/b3/9458adb9472e61a998c8c4d95cfdfec91c73c53a375b30b1428310f923e4/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a", size = 1475533 }, - { url = "https://files.pythonhosted.org/packages/e4/7a/0a42d9571e35798de80aef4bb43a9b672aa7f8e58643d7bd1950398ffb0a/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3", size = 2268898 }, - { url = "https://files.pythonhosted.org/packages/d9/07/1255dc8d80271400126ed8db35a1795b1a2c098ac3a72645075d06fe5c5d/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b", size = 2425605 }, - { url = "https://files.pythonhosted.org/packages/84/df/5a3b4cf13780ef6f6942df67b138b03b7e79e9f1f08f57c49957d5867f6e/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4", size = 2375801 }, - { url = "https://files.pythonhosted.org/packages/8f/10/2348d068e8b0f635c8c86892788dac7a6b5c0cb12356620ab575775aad89/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d", size = 2520077 }, - { url = "https://files.pythonhosted.org/packages/32/d8/014b89fee5d4dce157d814303b0fce4d31385a2af4c41fed194b173b81ac/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8", size = 2338410 }, - { url = "https://files.pythonhosted.org/packages/bd/72/dfff0cc97f2a0776e1c9eb5bef1ddfd45f46246c6533b0191887a427bca5/kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50", size = 71853 }, - { url = "https://files.pythonhosted.org/packages/dc/85/220d13d914485c0948a00f0b9eb419efaf6da81b7d72e88ce2391f7aed8d/kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476", size = 65424 }, + { url = "https://files.pythonhosted.org/packages/e9/44/77429fa0a58f941d6e1c58da9efe08597d2e86bf2b2cce6626834f49d07b/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54", size = 122442 }, + { url = "https://files.pythonhosted.org/packages/e5/20/8c75caed8f2462d63c7fd65e16c832b8f76cda331ac9e615e914ee80bac9/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95", size = 65762 }, + { url = "https://files.pythonhosted.org/packages/f4/98/fe010f15dc7230f45bc4cf367b012d651367fd203caaa992fd1f5963560e/kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935", size = 64319 }, + { url = "https://files.pythonhosted.org/packages/8b/1b/b5d618f4e58c0675654c1e5051bcf42c776703edb21c02b8c74135541f60/kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb", size = 1334260 }, + { url = "https://files.pythonhosted.org/packages/b8/01/946852b13057a162a8c32c4c8d2e9ed79f0bb5d86569a40c0b5fb103e373/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02", size = 1426589 }, + { url = "https://files.pythonhosted.org/packages/70/d1/c9f96df26b459e15cf8a965304e6e6f4eb291e0f7a9460b4ad97b047561e/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51", size = 1541080 }, + { url = "https://files.pythonhosted.org/packages/d3/73/2686990eb8b02d05f3de759d6a23a4ee7d491e659007dd4c075fede4b5d0/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052", size = 1470049 }, + { url = "https://files.pythonhosted.org/packages/a7/4b/2db7af3ed3af7c35f388d5f53c28e155cd402a55432d800c543dc6deb731/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18", size = 1426376 }, + { url = "https://files.pythonhosted.org/packages/05/83/2857317d04ea46dc5d115f0df7e676997bbd968ced8e2bd6f7f19cfc8d7f/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545", size = 2222231 }, + { url = "https://files.pythonhosted.org/packages/0d/b5/866f86f5897cd4ab6d25d22e403404766a123f138bd6a02ecb2cdde52c18/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b", size = 2368634 }, + { url = "https://files.pythonhosted.org/packages/c1/ee/73de8385403faba55f782a41260210528fe3273d0cddcf6d51648202d6d0/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36", size = 2329024 }, + { url = "https://files.pythonhosted.org/packages/a1/e7/cd101d8cd2cdfaa42dc06c433df17c8303d31129c9fdd16c0ea37672af91/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3", size = 2468484 }, + { url = "https://files.pythonhosted.org/packages/e1/72/84f09d45a10bc57a40bb58b81b99d8f22b58b2040c912b7eb97ebf625bf2/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523", size = 2284078 }, + { url = "https://files.pythonhosted.org/packages/d2/d4/71828f32b956612dc36efd7be1788980cb1e66bfb3706e6dec9acad9b4f9/kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d", size = 46645 }, + { url = "https://files.pythonhosted.org/packages/a1/65/d43e9a20aabcf2e798ad1aff6c143ae3a42cf506754bcb6a7ed8259c8425/kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b", size = 56022 }, + { url = "https://files.pythonhosted.org/packages/35/b3/9f75a2e06f1b4ca00b2b192bc2b739334127d27f1d0625627ff8479302ba/kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376", size = 48536 }, + { url = "https://files.pythonhosted.org/packages/97/9c/0a11c714cf8b6ef91001c8212c4ef207f772dd84540104952c45c1f0a249/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2", size = 121808 }, + { url = "https://files.pythonhosted.org/packages/f2/d8/0fe8c5f5d35878ddd135f44f2af0e4e1d379e1c7b0716f97cdcb88d4fd27/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a", size = 65531 }, + { url = "https://files.pythonhosted.org/packages/80/c5/57fa58276dfdfa612241d640a64ca2f76adc6ffcebdbd135b4ef60095098/kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee", size = 63894 }, + { url = "https://files.pythonhosted.org/packages/8b/e9/26d3edd4c4ad1c5b891d8747a4f81b1b0aba9fb9721de6600a4adc09773b/kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640", size = 1369296 }, + { url = "https://files.pythonhosted.org/packages/b6/67/3f4850b5e6cffb75ec40577ddf54f7b82b15269cc5097ff2e968ee32ea7d/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f", size = 1461450 }, + { url = "https://files.pythonhosted.org/packages/52/be/86cbb9c9a315e98a8dc6b1d23c43cffd91d97d49318854f9c37b0e41cd68/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483", size = 1579168 }, + { url = "https://files.pythonhosted.org/packages/0f/00/65061acf64bd5fd34c1f4ae53f20b43b0a017a541f242a60b135b9d1e301/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258", size = 1507308 }, + { url = "https://files.pythonhosted.org/packages/21/e4/c0b6746fd2eb62fe702118b3ca0cb384ce95e1261cfada58ff693aeec08a/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e", size = 1464186 }, + { url = "https://files.pythonhosted.org/packages/0a/0f/529d0a9fffb4d514f2782c829b0b4b371f7f441d61aa55f1de1c614c4ef3/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107", size = 2247877 }, + { url = "https://files.pythonhosted.org/packages/d1/e1/66603ad779258843036d45adcbe1af0d1a889a07af4635f8b4ec7dccda35/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948", size = 2404204 }, + { url = "https://files.pythonhosted.org/packages/8d/61/de5fb1ca7ad1f9ab7970e340a5b833d735df24689047de6ae71ab9d8d0e7/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038", size = 2352461 }, + { url = "https://files.pythonhosted.org/packages/ba/d2/0edc00a852e369827f7e05fd008275f550353f1f9bcd55db9363d779fc63/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383", size = 2501358 }, + { url = "https://files.pythonhosted.org/packages/84/15/adc15a483506aec6986c01fb7f237c3aec4d9ed4ac10b756e98a76835933/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520", size = 2314119 }, + { url = "https://files.pythonhosted.org/packages/36/08/3a5bb2c53c89660863a5aa1ee236912269f2af8762af04a2e11df851d7b2/kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b", size = 46367 }, + { url = "https://files.pythonhosted.org/packages/19/93/c05f0a6d825c643779fc3c70876bff1ac221f0e31e6f701f0e9578690d70/kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb", size = 55884 }, + { url = "https://files.pythonhosted.org/packages/d2/f9/3828d8f21b6de4279f0667fb50a9f5215e6fe57d5ec0d61905914f5b6099/kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a", size = 48528 }, ] [[package]] name = "libusb1" -version = "3.2.0" +version = "3.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d9/b7/9e833af6cb52fa2aece1c6a1378667ca0172bead14f63ffccc3cb9862df3/libusb1-3.2.0.tar.gz", hash = "sha256:a11a6095e718cd49418a96329314da271cca6be7b4317a142724523371ac8961", size = 105601 } +sdist = { url = "https://files.pythonhosted.org/packages/af/19/53ecbfb96d6832f2272d13b84658c360802fcfff7c0c497ab8f6bf15ac40/libusb1-3.1.0.tar.gz", hash = "sha256:4ee9b0a55f8bd0b3ea7017ae919a6c1f439af742c4a4b04543c5fd7af89b828c", size = 83013 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/35/d5bde9434fc734709960a94cc489d487184d0ab08e5867311d5a4c64fcea/libusb1-3.2.0-py3-none-any.whl", hash = "sha256:048d4fb79021ec05af667a32e51a911578fc63ab3ed48a4f4fe0f67da797f416", size = 65829 }, - { url = "https://files.pythonhosted.org/packages/a3/cd/ef05b2c67fff2d704aa0325993187ce6a6d04f40ba4be953766b47f5f949/libusb1-3.2.0-py3-none-win32.whl", hash = "sha256:5dc48d6f5207e184cb53278527e7d8e5f4051d8bc419bd15b564c37dc5cca268", size = 127781 }, - { url = "https://files.pythonhosted.org/packages/f9/82/8bcadf2794fa2d39ec100a4f3945db58c316d55c1a0e79ac2cf81c754282/libusb1-3.2.0-py3-none-win_amd64.whl", hash = "sha256:b13acc618263348c91bc4476fadada47be98b7924d6f60e79e3f1da67ac39ddc", size = 139410 }, + { url = "https://files.pythonhosted.org/packages/85/5c/9169aea7690df382b677d9f725accc3ec864849c5ab49991e3823a942392/libusb1-3.1.0-py3-none-any.whl", hash = "sha256:9d9f16e2c199cab91f48ead585d3f5ec7e8e4be428a25ddfed22abf786fa9b3a", size = 62368 }, + { url = "https://files.pythonhosted.org/packages/2f/84/d851eb09565ff72b0dfbb988f4e1c79d3746c16eda5bb8e81ec6ce3bb16e/libusb1-3.1.0-py3-none-win32.whl", hash = "sha256:bc7874302565721f443a27d8182fcc7152e5b560523f12f1377b130f473e4a0c", size = 127838 }, + { url = "https://files.pythonhosted.org/packages/02/a5/620d383ec17051f42a907f21517eb498ddecd45b2b81e46cc42e6ec4038e/libusb1-3.1.0-py3-none-win_amd64.whl", hash = "sha256:77a06ecfb3d002d7c2ce369e28d0138b292fe8db8a3d102b73fda231a716dd35", size = 140380 }, ] [[package]] @@ -953,8 +959,8 @@ wheels = [ [[package]] name = "metadrive-simulator" -version = "0.4.2.4" -source = { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl" } +version = "0.4.2.3" +source = { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal/metadrive_simulator-0.4.2.3-py3-none-any.whl" } dependencies = [ { name = "filelock" }, { name = "gymnasium" }, @@ -974,7 +980,7 @@ dependencies = [ { name = "yapf" }, ] wheels = [ - { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl", hash = "sha256:fbf0ea9be67e65cd45d38ff930e3d49f705dd76c9ddbd1e1482e3f87b61efcef" }, + { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal/metadrive_simulator-0.4.2.3-py3-none-any.whl", hash = "sha256:6242d4e37e6c592d5eb1cadf497637540d3b754b89813a88c50a93c7fc88b02d" }, ] [package.metadata] @@ -1010,7 +1016,7 @@ version = "1.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, { name = "ghp-import" }, { name = "jinja2" }, { name = "markdown" }, @@ -1048,8 +1054,8 @@ version = "0.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyperclip" }, - { name = "python3-xlib", marker = "sys_platform == 'linux'" }, - { name = "rubicon-objc", marker = "sys_platform == 'darwin'" }, + { name = "python3-xlib", marker = "platform_system == 'Linux'" }, + { name = "rubicon-objc", marker = "platform_system == 'Darwin'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/28/fa/b2ba8229b9381e8f6381c1dcae6f4159a7f72349e414ed19cfbbd1817173/MouseInfo-0.1.3.tar.gz", hash = "sha256:2c62fb8885062b8e520a3cce0a297c657adcc08c60952eb05bc8256ef6f7f6e7", size = 10850 } @@ -1130,27 +1136,25 @@ wheels = [ [[package]] name = "mypy" -version = "1.14.1" +version = "1.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/21/7e9e523537991d145ab8a0a2fd98548d67646dc2aaaf6091c31ad883e7c1/mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e", size = 3152532 } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, - { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, - { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, - { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, - { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, - { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, - { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 }, - { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 }, - { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 }, - { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 }, - { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 }, - { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 }, - { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, + { url = "https://files.pythonhosted.org/packages/d0/19/de0822609e5b93d02579075248c7aa6ceaddcea92f00bf4ea8e4c22e3598/mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d", size = 10939027 }, + { url = "https://files.pythonhosted.org/packages/c8/71/6950fcc6ca84179137e4cbf7cf41e6b68b4a339a1f5d3e954f8c34e02d66/mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d", size = 10108699 }, + { url = "https://files.pythonhosted.org/packages/26/50/29d3e7dd166e74dc13d46050b23f7d6d7533acf48f5217663a3719db024e/mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b", size = 12506263 }, + { url = "https://files.pythonhosted.org/packages/3f/1d/676e76f07f7d5ddcd4227af3938a9c9640f293b7d8a44dd4ff41d4db25c1/mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73", size = 12984688 }, + { url = "https://files.pythonhosted.org/packages/9c/03/5a85a30ae5407b1d28fab51bd3e2103e52ad0918d1e68f02a7778669a307/mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca", size = 9626811 }, + { url = "https://files.pythonhosted.org/packages/fb/31/c526a7bd2e5c710ae47717c7a5f53f616db6d9097caf48ad650581e81748/mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5", size = 11077900 }, + { url = "https://files.pythonhosted.org/packages/83/67/b7419c6b503679d10bd26fc67529bc6a1f7a5f220bbb9f292dc10d33352f/mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e", size = 10074818 }, + { url = "https://files.pythonhosted.org/packages/ba/07/37d67048786ae84e6612575e173d713c9a05d0ae495dde1e68d972207d98/mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2", size = 12589275 }, + { url = "https://files.pythonhosted.org/packages/1f/17/b1018c6bb3e9f1ce3956722b3bf91bff86c1cefccca71cec05eae49d6d41/mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0", size = 13037783 }, + { url = "https://files.pythonhosted.org/packages/cb/32/cd540755579e54a88099aee0287086d996f5a24281a673f78a0e14dba150/mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2", size = 9726197 }, + { url = "https://files.pythonhosted.org/packages/3b/86/72ce7f57431d87a7ff17d442f521146a6585019eb8f4f31b7c02801f78ad/mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a", size = 2647043 }, ] [[package]] @@ -1292,7 +1296,7 @@ dependencies = [ { name = "setuptools" }, { name = "smbus2" }, { name = "sounddevice" }, - { name = "spidev", marker = "sys_platform == 'linux'" }, + { name = "spidev", marker = "platform_system == 'Linux'" }, { name = "sympy" }, { name = "tqdm" }, { name = "websocket-client" }, @@ -1311,6 +1315,7 @@ dev = [ { name = "pyautogui" }, { name = "pyopencl", marker = "platform_machine != 'aarch64'" }, { name = "pyprof2calltree" }, + { name = "pyqt5", marker = "platform_machine == 'x86_64'" }, { name = "pytools", marker = "platform_machine != 'aarch64'" }, { name = "pywinctl" }, { name = "tabulate" }, @@ -1367,7 +1372,7 @@ requires-dist = [ { name = "libusb1" }, { name = "lru-dict", marker = "extra == 'dev'" }, { name = "matplotlib", marker = "extra == 'dev'" }, - { name = "metadrive-simulator", marker = "platform_machine != 'aarch64' and extra == 'tools'", url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl" }, + { name = "metadrive-simulator", marker = "platform_machine != 'aarch64' and extra == 'tools'", url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal/metadrive_simulator-0.4.2.3-py3-none-any.whl" }, { name = "mkdocs", marker = "extra == 'docs'" }, { name = "mypy", marker = "extra == 'testing'" }, { name = "natsort", marker = "extra == 'docs'" }, @@ -1385,6 +1390,7 @@ requires-dist = [ { name = "pyopencl", marker = "platform_machine != 'aarch64' and extra == 'dev'" }, { name = "pyopenssl", specifier = "<24.3.0" }, { name = "pyprof2calltree", marker = "extra == 'dev'" }, + { name = "pyqt5", marker = "platform_machine == 'x86_64' and extra == 'dev'", specifier = "==5.15.2" }, { name = "pyserial" }, { name = "pytest", marker = "extra == 'testing'" }, { name = "pytest-asyncio", marker = "extra == 'testing'" }, @@ -1408,7 +1414,7 @@ requires-dist = [ { name = "setuptools" }, { name = "smbus2" }, { name = "sounddevice" }, - { name = "spidev", marker = "sys_platform == 'linux'" }, + { name = "spidev", marker = "platform_system == 'Linux'" }, { name = "sympy" }, { name = "tabulate", marker = "extra == 'dev'" }, { name = "tqdm" }, @@ -1491,32 +1497,32 @@ wheels = [ [[package]] name = "pillow" -version = "11.1.0" +version = "11.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } +sdist = { url = "https://files.pythonhosted.org/packages/a5/26/0d95c04c868f6bdb0c447e3ee2de5564411845e36a858cfd63766bc7b563/pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739", size = 46737780 } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, - { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, - { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, - { url = "https://files.pythonhosted.org/packages/e4/c2/e25199e7e4e71d64eeb869f5b72c7ddec70e0a87926398785ab944d92375/pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", size = 4402945 }, - { url = "https://files.pythonhosted.org/packages/c1/ed/51d6136c9d5911f78632b1b86c45241c712c5a80ed7fa7f9120a5dff1eba/pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", size = 4361228 }, - { url = "https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", size = 4484021 }, - { url = "https://files.pythonhosted.org/packages/39/db/0b3c1a5018117f3c1d4df671fb8e47d08937f27519e8614bbe86153b65a5/pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", size = 4287449 }, - { url = "https://files.pythonhosted.org/packages/d9/58/bc128da7fea8c89fc85e09f773c4901e95b5936000e6f303222490c052f3/pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", size = 4419972 }, - { url = "https://files.pythonhosted.org/packages/5f/bb/58f34379bde9fe197f51841c5bbe8830c28bbb6d3801f16a83b8f2ad37df/pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", size = 2291201 }, - { url = "https://files.pythonhosted.org/packages/3a/c6/fce9255272bcf0c39e15abd2f8fd8429a954cf344469eaceb9d0d1366913/pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761", size = 2625686 }, - { url = "https://files.pythonhosted.org/packages/c8/52/8ba066d569d932365509054859f74f2a9abee273edcef5cd75e4bc3e831e/pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", size = 2375194 }, - { url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 }, - { url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 }, - { url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 }, - { url = "https://files.pythonhosted.org/packages/8c/aa/7f29711f26680eab0bcd3ecdd6d23ed6bce180d82e3f6380fb7ae35fcf3b/pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", size = 4412999 }, - { url = "https://files.pythonhosted.org/packages/c8/c4/8f0fe3b9e0f7196f6d0bbb151f9fba323d72a41da068610c4c960b16632a/pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", size = 4368819 }, - { url = "https://files.pythonhosted.org/packages/38/0d/84200ed6a871ce386ddc82904bfadc0c6b28b0c0ec78176871a4679e40b3/pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", size = 4496081 }, - { url = "https://files.pythonhosted.org/packages/84/9c/9bcd66f714d7e25b64118e3952d52841a4babc6d97b6d28e2261c52045d4/pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", size = 4296513 }, - { url = "https://files.pythonhosted.org/packages/db/61/ada2a226e22da011b45f7104c95ebda1b63dcbb0c378ad0f7c2a710f8fd2/pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", size = 4431298 }, - { url = "https://files.pythonhosted.org/packages/e7/c4/fc6e86750523f367923522014b821c11ebc5ad402e659d8c9d09b3c9d70c/pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", size = 2291630 }, - { url = "https://files.pythonhosted.org/packages/08/5c/2104299949b9d504baf3f4d35f73dbd14ef31bbd1ddc2c1b66a5b7dfda44/pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", size = 2626369 }, - { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, + { url = "https://files.pythonhosted.org/packages/f0/eb/f7e21b113dd48a9c97d364e0915b3988c6a0b6207652f5a92372871b7aa4/pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc", size = 3154705 }, + { url = "https://files.pythonhosted.org/packages/25/b3/2b54a1d541accebe6bd8b1358b34ceb2c509f51cb7dcda8687362490da5b/pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a", size = 2979222 }, + { url = "https://files.pythonhosted.org/packages/20/12/1a41eddad8265c5c19dda8fb6c269ce15ee25e0b9f8f26286e6202df6693/pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3", size = 4190220 }, + { url = "https://files.pythonhosted.org/packages/a9/9b/8a8c4d07d77447b7457164b861d18f5a31ae6418ef5c07f6f878fa09039a/pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5", size = 4291399 }, + { url = "https://files.pythonhosted.org/packages/fc/e4/130c5fab4a54d3991129800dd2801feeb4b118d7630148cd67f0e6269d4c/pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b", size = 4202709 }, + { url = "https://files.pythonhosted.org/packages/39/63/b3fc299528d7df1f678b0666002b37affe6b8751225c3d9c12cf530e73ed/pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa", size = 4372556 }, + { url = "https://files.pythonhosted.org/packages/c6/a6/694122c55b855b586c26c694937d36bb8d3b09c735ff41b2f315c6e66a10/pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306", size = 4287187 }, + { url = "https://files.pythonhosted.org/packages/ba/a9/f9d763e2671a8acd53d29b1e284ca298bc10a595527f6be30233cdb9659d/pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9", size = 4418468 }, + { url = "https://files.pythonhosted.org/packages/6e/0e/b5cbad2621377f11313a94aeb44ca55a9639adabcaaa073597a1925f8c26/pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5", size = 2249249 }, + { url = "https://files.pythonhosted.org/packages/dc/83/1470c220a4ff06cd75fc609068f6605e567ea51df70557555c2ab6516b2c/pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291", size = 2566769 }, + { url = "https://files.pythonhosted.org/packages/52/98/def78c3a23acee2bcdb2e52005fb2810ed54305602ec1bfcfab2bda6f49f/pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9", size = 2254611 }, + { url = "https://files.pythonhosted.org/packages/1c/a3/26e606ff0b2daaf120543e537311fa3ae2eb6bf061490e4fea51771540be/pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923", size = 3147642 }, + { url = "https://files.pythonhosted.org/packages/4f/d5/1caabedd8863526a6cfa44ee7a833bd97f945dc1d56824d6d76e11731939/pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903", size = 2978999 }, + { url = "https://files.pythonhosted.org/packages/d9/ff/5a45000826a1aa1ac6874b3ec5a856474821a1b59d838c4f6ce2ee518fe9/pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4", size = 4196794 }, + { url = "https://files.pythonhosted.org/packages/9d/21/84c9f287d17180f26263b5f5c8fb201de0f88b1afddf8a2597a5c9fe787f/pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f", size = 4300762 }, + { url = "https://files.pythonhosted.org/packages/84/39/63fb87cd07cc541438b448b1fed467c4d687ad18aa786a7f8e67b255d1aa/pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9", size = 4210468 }, + { url = "https://files.pythonhosted.org/packages/7f/42/6e0f2c2d5c60f499aa29be14f860dd4539de322cd8fb84ee01553493fb4d/pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7", size = 4381824 }, + { url = "https://files.pythonhosted.org/packages/31/69/1ef0fb9d2f8d2d114db982b78ca4eeb9db9a29f7477821e160b8c1253f67/pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6", size = 4296436 }, + { url = "https://files.pythonhosted.org/packages/44/ea/dad2818c675c44f6012289a7c4f46068c548768bc6c7f4e8c4ae5bbbc811/pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc", size = 4429714 }, + { url = "https://files.pythonhosted.org/packages/af/3a/da80224a6eb15bba7a0dcb2346e2b686bb9bf98378c0b4353cd88e62b171/pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6", size = 2249631 }, + { url = "https://files.pythonhosted.org/packages/57/97/73f756c338c1d86bb802ee88c3cab015ad7ce4b838f8a24f16b676b1ac7c/pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47", size = 2567533 }, + { url = "https://files.pythonhosted.org/packages/0b/30/2b61876e2722374558b871dfbfcbe4e406626d63f4f6ed92e9c8e24cac37/pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25", size = 2254890 }, ] [[package]] @@ -1542,7 +1548,7 @@ name = "portalocker" version = "2.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "pywin32", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 } wheels = [ @@ -1610,31 +1616,31 @@ wheels = [ [[package]] name = "protobuf" -version = "5.29.2" +version = "5.29.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/73/4e6295c1420a9d20c9c351db3a36109b4c9aa601916cb7c6871e3196a1ca/protobuf-5.29.2.tar.gz", hash = "sha256:b2cc8e8bb7c9326996f0e160137b0861f1a82162502658df2951209d0cb0309e", size = 424901 } +sdist = { url = "https://files.pythonhosted.org/packages/d2/4f/1639b7b1633d8fd55f216ba01e21bf2c43384ab25ef3ddb35d85a52033e8/protobuf-5.29.1.tar.gz", hash = "sha256:683be02ca21a6ffe80db6dd02c0b5b2892322c59ca57fd6c872d652cb80549cb", size = 424965 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/42/6db5387124708d619ffb990a846fb123bee546f52868039f8fa964c5bc54/protobuf-5.29.2-cp310-abi3-win32.whl", hash = "sha256:c12ba8249f5624300cf51c3d0bfe5be71a60c63e4dcf51ffe9a68771d958c851", size = 422697 }, - { url = "https://files.pythonhosted.org/packages/6c/38/2fcc968b377b531882d6ab2ac99b10ca6d00108394f6ff57c2395fb7baff/protobuf-5.29.2-cp310-abi3-win_amd64.whl", hash = "sha256:842de6d9241134a973aab719ab42b008a18a90f9f07f06ba480df268f86432f9", size = 434495 }, - { url = "https://files.pythonhosted.org/packages/cb/26/41debe0f6615fcb7e97672057524687ed86fcd85e3da3f031c30af8f0c51/protobuf-5.29.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a0c53d78383c851bfa97eb42e3703aefdc96d2036a41482ffd55dc5f529466eb", size = 417812 }, - { url = "https://files.pythonhosted.org/packages/e4/20/38fc33b60dcfb380507b99494aebe8c34b68b8ac7d32808c4cebda3f6f6b/protobuf-5.29.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:494229ecd8c9009dd71eda5fd57528395d1eacdf307dbece6c12ad0dd09e912e", size = 319562 }, - { url = "https://files.pythonhosted.org/packages/90/4d/c3d61e698e0e41d926dbff6aa4e57428ab1a6fc3b5e1deaa6c9ec0fd45cf/protobuf-5.29.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:b6b0d416bbbb9d4fbf9d0561dbfc4e324fd522f61f7af0fe0f282ab67b22477e", size = 319662 }, - { url = "https://files.pythonhosted.org/packages/f3/fd/c7924b4c2a1c61b8f4b64edd7a31ffacf63432135a2606f03a2f0d75a750/protobuf-5.29.2-py3-none-any.whl", hash = "sha256:fde4554c0e578a5a0bcc9a276339594848d1e89f9ea47b4427c80e5d72f90181", size = 172539 }, + { url = "https://files.pythonhosted.org/packages/50/c7/28669b04691a376cf7d0617d612f126aa0fff763d57df0142f9bf474c5b8/protobuf-5.29.1-cp310-abi3-win32.whl", hash = "sha256:22c1f539024241ee545cbcb00ee160ad1877975690b16656ff87dde107b5f110", size = 422706 }, + { url = "https://files.pythonhosted.org/packages/e3/33/dc7a7712f457456b7e0b16420ab8ba1cc8686751d3f28392eb43d0029ab9/protobuf-5.29.1-cp310-abi3-win_amd64.whl", hash = "sha256:1fc55267f086dd4050d18ef839d7bd69300d0d08c2a53ca7df3920cc271a3c34", size = 434505 }, + { url = "https://files.pythonhosted.org/packages/e5/39/44239fb1c6ec557e1731d996a5de89a9eb1ada7a92491fcf9c5d714052ed/protobuf-5.29.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:d473655e29c0c4bbf8b69e9a8fb54645bc289dead6d753b952e7aa660254ae18", size = 417822 }, + { url = "https://files.pythonhosted.org/packages/fb/4a/ec56f101d38d4bef2959a9750209809242d86cf8b897db00f2f98bfa360e/protobuf-5.29.1-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5ba1d0e4c8a40ae0496d0e2ecfdbb82e1776928a205106d14ad6985a09ec155", size = 319572 }, + { url = "https://files.pythonhosted.org/packages/04/52/c97c58a33b3d6c89a8138788576d372a90a6556f354799971c6b4d16d871/protobuf-5.29.1-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ee1461b3af56145aca2800e6a3e2f928108c749ba8feccc6f5dd0062c410c0d", size = 319671 }, + { url = "https://files.pythonhosted.org/packages/3b/24/c8c49df8f6587719e1d400109b16c10c6902d0c9adddc8fff82840146f99/protobuf-5.29.1-py3-none-any.whl", hash = "sha256:32600ddb9c2a53dedc25b8581ea0f1fd8ea04956373c0c07577ce58d312522e0", size = 172547 }, ] [[package]] name = "psutil" -version = "6.1.1" +version = "6.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1f/5a/07871137bb752428aa4b659f910b399ba6f291156bdea939be3e96cae7cb/psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5", size = 508502 } +sdist = { url = "https://files.pythonhosted.org/packages/26/10/2a30b13c61e7cf937f4adf90710776b7918ed0a9c434e2c38224732af310/psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a", size = 508565 } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/99/ca79d302be46f7bdd8321089762dd4476ee725fce16fc2b2e1dbba8cac17/psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8", size = 247511 }, - { url = "https://files.pythonhosted.org/packages/0b/6b/73dbde0dd38f3782905d4587049b9be64d76671042fdcaf60e2430c6796d/psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377", size = 248985 }, - { url = "https://files.pythonhosted.org/packages/17/38/c319d31a1d3f88c5b79c68b3116c129e5133f1822157dd6da34043e32ed6/psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003", size = 284488 }, - { url = "https://files.pythonhosted.org/packages/9c/39/0f88a830a1c8a3aba27fededc642da37613c57cbff143412e3536f89784f/psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160", size = 287477 }, - { url = "https://files.pythonhosted.org/packages/47/da/99f4345d4ddf2845cb5b5bd0d93d554e84542d116934fde07a0c50bd4e9f/psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3", size = 289017 }, - { url = "https://files.pythonhosted.org/packages/38/53/bd755c2896f4461fd4f36fa6a6dcb66a88a9e4b9fd4e5b66a77cf9d4a584/psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53", size = 250602 }, - { url = "https://files.pythonhosted.org/packages/7b/d7/7831438e6c3ebbfa6e01a927127a6cb42ad3ab844247f3c5b96bea25d73d/psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649", size = 254444 }, + { url = "https://files.pythonhosted.org/packages/01/9e/8be43078a171381953cfee33c07c0d628594b5dbfc5157847b85022c2c1b/psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688", size = 247762 }, + { url = "https://files.pythonhosted.org/packages/1d/cb/313e80644ea407f04f6602a9e23096540d9dc1878755f3952ea8d3d104be/psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e", size = 248777 }, + { url = "https://files.pythonhosted.org/packages/65/8e/bcbe2025c587b5d703369b6a75b65d41d1367553da6e3f788aff91eaf5bd/psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38", size = 284259 }, + { url = "https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b", size = 287255 }, + { url = "https://files.pythonhosted.org/packages/27/c2/d034856ac47e3b3cdfa9720d0e113902e615f4190d5d1bdb8df4b2015fb2/psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a", size = 288804 }, + { url = "https://files.pythonhosted.org/packages/ea/55/5389ed243c878725feffc0d6a3bc5ef6764312b6fc7c081faaa2cfa7ef37/psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e", size = 250386 }, + { url = "https://files.pythonhosted.org/packages/11/91/87fa6f060e649b1e1a7b19a4f5869709fbf750b7c8c262ee776ec32f3028/psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be", size = 254228 }, ] [[package]] @@ -1679,10 +1685,10 @@ dependencies = [ { name = "mouseinfo" }, { name = "pygetwindow" }, { name = "pymsgbox" }, - { name = "pyobjc-core", marker = "sys_platform == 'darwin'" }, - { name = "pyobjc-framework-quartz", marker = "sys_platform == 'darwin'" }, + { name = "pyobjc-core", marker = "platform_system == 'Darwin'" }, + { name = "pyobjc-framework-quartz", marker = "platform_system == 'Darwin'" }, { name = "pyscreeze" }, - { name = "python3-xlib", marker = "sys_platform == 'linux'" }, + { name = "python3-xlib", marker = "platform_system == 'Linux'" }, { name = "pytweening" }, ] sdist = { url = "https://files.pythonhosted.org/packages/65/ff/cdae0a8c2118a0de74b6cf4cbcdcaf8fd25857e6c3f205ce4b1794b27814/PyAutoGUI-0.9.54.tar.gz", hash = "sha256:dd1d29e8fd118941cb193f74df57e5c6ff8e9253b99c7b04f39cfc69f3ae04b2", size = 61236 } @@ -1775,11 +1781,11 @@ sdist = { url = "https://files.pythonhosted.org/packages/e1/70/c7a4f46dbf06048c6 [[package]] name = "pygments" -version = "2.19.0" +version = "2.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d3/c0/9c9832e5be227c40e1ce774d493065f83a91d6430baa7e372094e9683a45/pygments-2.19.0.tar.gz", hash = "sha256:afc4146269910d4bdfabcd27c24923137a74d562a23a320a41a55ad303e19783", size = 4967733 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/dc/fde3e7ac4d279a331676829af4afafd113b34272393d73f610e8f0329221/pygments-2.19.0-py3-none-any.whl", hash = "sha256:4755e6e64d22161d5b61432c0600c923c5927214e7c956e31c23923c89251a9b", size = 1225305 }, + { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, ] [[package]] @@ -1819,10 +1825,10 @@ name = "pymonctl" version = "0.92" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ewmhlib", marker = "sys_platform == 'linux'" }, - { name = "pyobjc", marker = "sys_platform == 'darwin'" }, - { name = "python-xlib", marker = "sys_platform == 'linux'" }, - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "ewmhlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, + { name = "pyobjc", marker = "(platform_machine != 'aarch64' and sys_platform == 'darwin') or (platform_system != 'Linux' and sys_platform == 'darwin')" }, + { name = "python-xlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, + { name = "pywin32", marker = "(platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" }, { name = "typing-extensions" }, ] wheels = [ @@ -4367,11 +4373,11 @@ wheels = [ [[package]] name = "pyparsing" -version = "3.2.1" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694 } +sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/e5aeee5387091148a19e1145f63606619cb5f20b83fccb63efae6474e7b2/pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c", size = 920984 } wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716 }, + { url = "https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", size = 106921 }, ] [[package]] @@ -4386,6 +4392,35 @@ version = "1.4.5" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ca/2a/e9a76261183b4b5e059a6625d7aae0bcb0a77622bc767d4497148ce2e218/pyprof2calltree-1.4.5.tar.gz", hash = "sha256:a635672ff31677486350b2be9a823ef92f740e6354a6aeda8fa4a8a3768e8f2f", size = 10080 } +[[package]] +name = "pyqt5" +version = "5.15.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyqt5-sip" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/6c/640e3f5c734c296a7193079a86842a789edb7988dca39eab44579088a1d1/PyQt5-5.15.2.tar.gz", hash = "sha256:372b08dc9321d1201e4690182697c5e7ffb2e0770e6b4a45519025134b12e4fc", size = 3265445 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/28/fcaf2aeede42456538d1543aefa253d70282bf326f5f795c99233366b66f/PyQt5-5.15.2-5.15.2-cp35.cp36.cp37.cp38.cp39-abi3-macosx_10_13_intel.whl", hash = "sha256:894ca4ae767a8d6cf5903784b71f755073c78cb8c167eecf6e4ed6b3b055ac6a", size = 47599356 }, + { url = "https://files.pythonhosted.org/packages/91/cf/cc705497cdae04c3c0bc34f94b91e31b6585bb65eb561f18473c998caae1/PyQt5-5.15.2-5.15.2-cp35.cp36.cp37.cp38.cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:29889845688a54d62820585ad5b2e0200a36b304ff3d7a555e95599f110ba4ce", size = 68328841 }, +] + +[[package]] +name = "pyqt5-sip" +version = "12.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/cd/f6f957107447bc53e398f6149f55a7f335c434f201e77dcfb8a3c20dc42c/pyqt5_sip-12.16.1.tar.gz", hash = "sha256:8c831f8b619811a32369d72339faa50ae53a963f5fdfa4d71f845c63e9673125", size = 103975 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/69/b23bb48eeea59d934587ae5e11d9fce2cfa0536a311c78a177190134a62d/PyQt5_sip-12.16.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09bfdb5f9adea15a542cbe4b89873a6b290c4f1669f66bb5f1a24993ce8bbdd0", size = 122619 }, + { url = "https://files.pythonhosted.org/packages/30/b7/78f68147ce4dfac84d705a9dbbb1c41878a365597fa08918bf2bdfd86809/PyQt5_sip-12.16.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:98b99fcdebbbfc999f4ab10829749151eb371b79201ecd98f20e934c16d0193e", size = 276217 }, + { url = "https://files.pythonhosted.org/packages/3c/01/0387b81f4b0797cb3762e1a2cbbe17086b7c15ba13de37e0f6e94b601a18/PyQt5_sip-12.16.1-cp311-cp311-win32.whl", hash = "sha256:67dbdc1b3be045caebfc75ee87966e23c6bee61d94cb634ddd71b634c9089890", size = 49044 }, + { url = "https://files.pythonhosted.org/packages/9a/96/67914c5e17456365b9d7bc71d6eec2a878340904aa9905ae48554a3f6f18/PyQt5_sip-12.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:8afd633d5f35e4e5205680d310800d10d30fcbfb6bb7b852bfaa31097c1be449", size = 58997 }, + { url = "https://files.pythonhosted.org/packages/7f/3d/8dc6b2ef0132ab1cc534485905b594e6f4176176924e54e35a3f6a0fb164/PyQt5_sip-12.16.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f6724c590de3d556c730ebda8b8f906b38373934472209e94d99357b52b56f5f", size = 124549 }, + { url = "https://files.pythonhosted.org/packages/45/eb/fa72094f2ca861941d38a4df49d0a34bd024972cd458f516ef3c65d128e3/PyQt5_sip-12.16.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:633cba509a98bd626def951bb948d4e736635acbd0b7fabd7be55a3a096a8a0b", size = 281640 }, + { url = "https://files.pythonhosted.org/packages/12/a5/9439567dbf513bfc0fd71a5bb3797fae649338715749e89571ad86b4b3e3/PyQt5_sip-12.16.1-cp312-cp312-win32.whl", hash = "sha256:2b35ff92caa569e540675ffcd79ffbf3e7092cccf7166f89e2a8b388db80aa1c", size = 49428 }, + { url = "https://files.pythonhosted.org/packages/a7/33/d91e003b85ff7ab227d0fff236d48c18ada2f0cd49d5e35cb514867ba609/PyQt5_sip-12.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0f83f554727f43dfe92afbf3a8c51e83bb8b78c5f160b635d4359fad681cebe", size = 57957 }, +] + [[package]] name = "pyreadline3" version = "3.5.4" @@ -4424,7 +4459,7 @@ name = "pytest" version = "8.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "(platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, @@ -4436,14 +4471,14 @@ wheels = [ [[package]] name = "pytest-asyncio" -version = "0.25.1" +version = "0.25.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/04/0477a4bdd176ad678d148c075f43620b3f7a060ff61c7da48500b1fa8a75/pytest_asyncio-0.25.1.tar.gz", hash = "sha256:79be8a72384b0c917677e00daa711e07db15259f4d23203c59012bcd989d4aee", size = 53760 } +sdist = { url = "https://files.pythonhosted.org/packages/94/18/82fcb4ee47d66d99f6cd1efc0b11b2a25029f303c599a5afda7c1bca4254/pytest_asyncio-0.25.0.tar.gz", hash = "sha256:8c0610303c9e0442a5db8604505fc0f545456ba1528824842b37b4a626cbf609", size = 53298 } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/fb/efc7226b384befd98d0e00d8c4390ad57f33c8fde00094b85c5e07897def/pytest_asyncio-0.25.1-py3-none-any.whl", hash = "sha256:c84878849ec63ff2ca509423616e071ef9cd8cc93c053aa33b5b8fb70a990671", size = 19357 }, + { url = "https://files.pythonhosted.org/packages/88/56/2ee0cab25c11d4e38738a2a98c645a8f002e2ecf7b5ed774c70d53b92bb1/pytest_asyncio-0.25.0-py3-none-any.whl", hash = "sha256:db5432d18eac6b7e28b46dcd9b69921b55c3b1086e85febfe04e70b18d9e81b3", size = 19245 }, ] [[package]] @@ -4613,10 +4648,10 @@ name = "pywinbox" version = "0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ewmhlib", marker = "sys_platform == 'linux'" }, - { name = "pyobjc", marker = "sys_platform == 'darwin'" }, - { name = "python-xlib", marker = "sys_platform == 'linux'" }, - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "ewmhlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, + { name = "pyobjc", marker = "(platform_machine != 'aarch64' and sys_platform == 'darwin') or (platform_system != 'Linux' and sys_platform == 'darwin')" }, + { name = "python-xlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, + { name = "pywin32", marker = "(platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" }, { name = "typing-extensions" }, ] wheels = [ @@ -4628,11 +4663,11 @@ name = "pywinctl" version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ewmhlib", marker = "sys_platform == 'linux'" }, + { name = "ewmhlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, { name = "pymonctl" }, - { name = "pyobjc", marker = "sys_platform == 'darwin'" }, - { name = "python-xlib", marker = "sys_platform == 'linux'" }, - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "pyobjc", marker = "(platform_machine != 'aarch64' and sys_platform == 'darwin') or (platform_system != 'Linux' and sys_platform == 'darwin')" }, + { name = "python-xlib", marker = "platform_system != 'Darwin' and sys_platform == 'linux'" }, + { name = "pywin32", marker = "(platform_machine != 'aarch64' and platform_system == 'Linux' and sys_platform == 'win32') or (platform_system != 'Darwin' and platform_system != 'Linux' and sys_platform == 'win32')" }, { name = "pywinbox" }, { name = "typing-extensions" }, ] @@ -4730,7 +4765,7 @@ wheels = [ [[package]] name = "rerun-sdk" -version = "0.21.0" +version = "0.20.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -4740,23 +4775,23 @@ dependencies = [ { name = "typing-extensions" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/7b/2dda703d2d234e8bf73edc11c099bc14c04b6bad6f748b76ad0525925dd9/rerun_sdk-0.21.0-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:1e454ceea31c70ae9ec1bb26eaa82828661b7657ab4d2261ca0b94006d6a1975", size = 43464114 }, - { url = "https://files.pythonhosted.org/packages/c7/11/de8d1d375624edc7dae25a9d76b769cddb9090ca55b8fd7ce5f93b975cf5/rerun_sdk-0.21.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:84ecb77b0b5bac71b53e849801ff073de89fcd2f1e0ca0da62fb18fcbeceadf0", size = 41643016 }, - { url = "https://files.pythonhosted.org/packages/53/49/aefaa4f0e2ee685858aedaee2cc6cc4df8330055bdfbe88c6905e62d693d/rerun_sdk-0.21.0-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:919d921165c3238490dbe5bf00a062c68fdd2c54dc14aac6a1914c82edb5d9c8", size = 46355630 }, - { url = "https://files.pythonhosted.org/packages/10/63/405a1b601cf1253878b1aebef6764095b2e8139cf233a908c2ccc4ad4ffd/rerun_sdk-0.21.0-cp38-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:897649aadcab7014b78096f93c84c61c00a227b80adaf0dec279924b5aab53d8", size = 47790175 }, - { url = "https://files.pythonhosted.org/packages/87/5e/c7cf6379a7a42748f5961ec41faf0e38635c6e6d5cd95b63a2691f0b34dc/rerun_sdk-0.21.0-cp38-abi3-win_amd64.whl", hash = "sha256:2060bdb536a198f0f04789ba5ba771e66587e7851d668b3dfab257a5efa16819", size = 39216574 }, + { url = "https://files.pythonhosted.org/packages/23/ae/4f77bd62575f9b1eb38d47c2f7094e54b892ec435ae061531998866be24e/rerun_sdk-0.20.3-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:7a38db1f145726314164aa7632ace8c3c7025aa19e0a60312ecea25b5f454fc3", size = 41847844 }, + { url = "https://files.pythonhosted.org/packages/2c/b5/5f00bb7b884e193ff08ce910c64c7fd3d8e5b0c06b22f0d662ceea0e8f75/rerun_sdk-0.20.3-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:7ee9083d9072cd9d20c461f62f38b0360bbe10059a79ce2fbfae561c47ac36e4", size = 40049743 }, + { url = "https://files.pythonhosted.org/packages/47/21/892318008ff3b35a003659b4654176a0bf0d4c59f5005a4bc9f2715b262e/rerun_sdk-0.20.3-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:b3ec9fb763339b20b1d6aa03eae20d7ba7c5b9122ecd1f3b4bf89776250cc2ed", size = 44524933 }, + { url = "https://files.pythonhosted.org/packages/23/b2/55cc70aa034fb440f877080fdd1d87bbb4a4313446be52f35f868b209ed5/rerun_sdk-0.20.3-cp38-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:c30742b7629d9b151414feda54c42ac11bcaabab7a81edf732bfe4c1164ef613", size = 45975083 }, + { url = "https://files.pythonhosted.org/packages/f7/52/c2fc95798683c6685db80003233937ad04bcfa5adaab222b1cd5d0ad8c36/rerun_sdk-0.20.3-cp38-abi3-win_amd64.whl", hash = "sha256:5756809ce587519fd115ebd85104abb8fe59f5c3e192450f3128eb196b7cdcd3", size = 37473082 }, ] [[package]] name = "ruamel-yaml" -version = "0.18.9" +version = "0.18.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/8f/135c0b5292c36adf8b6ebd1f4747be709b67cfce23f6f16a4776131111a6/ruamel.yaml-0.18.9.tar.gz", hash = "sha256:59d0f8b10c658bd55ecd107e334d4117d766a2b9cc8f5176afcdadcff6f84a5e", size = 143739 } +sdist = { url = "https://files.pythonhosted.org/packages/29/81/4dfc17eb6ebb1aac314a3eb863c1325b907863a1b8b1382cdffcb6ac0ed9/ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b", size = 143362 } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/9c/a4f8d531861f7e00025672844ecfda1a653dc9147f91df5ac9f7aa09dc35/ruamel.yaml-0.18.9-py3-none-any.whl", hash = "sha256:c17d2a7ccf7fd2dd4b6d699111c37e94f12277a1db71e847ad7f3d19b8e3e9f4", size = 117578 }, + { url = "https://files.pythonhosted.org/packages/73/67/8ece580cc363331d9a53055130f86b096bf16e38156e33b1d3014fffda6b/ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636", size = 117761 }, ] [[package]] @@ -4796,27 +4831,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.8.6" +version = "0.8.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/00/089db7890ea3be5709e3ece6e46408d6f1e876026ec3fd081ee585fef209/ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5", size = 3473116 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/5e/683c7ef7a696923223e7d95ca06755d6e2acbc5fd8382b2912a28008137c/ruff-0.8.3.tar.gz", hash = "sha256:5e7558304353b84279042fc584a4f4cb8a07ae79b2bf3da1a7551d960b5626d3", size = 3378522 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/28/aa07903694637c2fa394a9f4fe93cf861ad8b09f1282fa650ef07ff9fe97/ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3", size = 10628735 }, - { url = "https://files.pythonhosted.org/packages/2b/43/827bb1448f1fcb0fb42e9c6edf8fb067ca8244923bf0ddf12b7bf949065c/ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1", size = 10386758 }, - { url = "https://files.pythonhosted.org/packages/df/93/fc852a81c3cd315b14676db3b8327d2bb2d7508649ad60bfdb966d60738d/ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807", size = 10007808 }, - { url = "https://files.pythonhosted.org/packages/94/e9/e0ed4af1794335fb280c4fac180f2bf40f6a3b859cae93a5a3ada27325ae/ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25", size = 10861031 }, - { url = "https://files.pythonhosted.org/packages/82/68/da0db02f5ecb2ce912c2bef2aa9fcb8915c31e9bc363969cfaaddbc4c1c2/ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d", size = 10388246 }, - { url = "https://files.pythonhosted.org/packages/ac/1d/b85383db181639019b50eb277c2ee48f9f5168f4f7c287376f2b6e2a6dc2/ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75", size = 11424693 }, - { url = "https://files.pythonhosted.org/packages/ac/b7/30bc78a37648d31bfc7ba7105b108cb9091cd925f249aa533038ebc5a96f/ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315", size = 12141921 }, - { url = "https://files.pythonhosted.org/packages/60/b3/ee0a14cf6a1fbd6965b601c88d5625d250b97caf0534181e151504498f86/ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188", size = 11692419 }, - { url = "https://files.pythonhosted.org/packages/ef/d6/c597062b2931ba3e3861e80bd2b147ca12b3370afc3889af46f29209037f/ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf", size = 12981648 }, - { url = "https://files.pythonhosted.org/packages/68/84/21f578c2a4144917985f1f4011171aeff94ab18dfa5303ac632da2f9af36/ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117", size = 11251801 }, - { url = "https://files.pythonhosted.org/packages/6c/aa/1ac02537c8edeb13e0955b5db86b5c050a1dcba54f6d49ab567decaa59c1/ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe", size = 10849857 }, - { url = "https://files.pythonhosted.org/packages/eb/00/020cb222252d833956cb3b07e0e40c9d4b984fbb2dc3923075c8f944497d/ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d", size = 10470852 }, - { url = "https://files.pythonhosted.org/packages/00/56/e6d6578202a0141cd52299fe5acb38b2d873565f4670c7a5373b637cf58d/ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a", size = 10972997 }, - { url = "https://files.pythonhosted.org/packages/be/31/dd0db1f4796bda30dea7592f106f3a67a8f00bcd3a50df889fbac58e2786/ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76", size = 11317760 }, - { url = "https://files.pythonhosted.org/packages/d4/70/cfcb693dc294e034c6fed837fa2ec98b27cc97a26db5d049345364f504bf/ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764", size = 8799729 }, - { url = "https://files.pythonhosted.org/packages/60/22/ae6bcaa0edc83af42751bd193138bfb7598b2990939d3e40494d6c00698c/ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905", size = 9673857 }, - { url = "https://files.pythonhosted.org/packages/91/f8/3765e053acd07baa055c96b2065c7fab91f911b3c076dfea71006666f5b0/ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162", size = 9149556 }, + { url = "https://files.pythonhosted.org/packages/f8/c4/bfdbb8b9c419ff3b52479af8581026eeaac3764946fdb463dec043441b7d/ruff-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:8d5d273ffffff0acd3db5bf626d4b131aa5a5ada1276126231c4174543ce20d6", size = 10535860 }, + { url = "https://files.pythonhosted.org/packages/ef/c5/0aabdc9314b4b6f051168ac45227e2aa8e1c6d82718a547455e40c9c9faa/ruff-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e4d66a21de39f15c9757d00c50c8cdd20ac84f55684ca56def7891a025d7e939", size = 10346327 }, + { url = "https://files.pythonhosted.org/packages/1a/78/4843a59e7e7b398d6019cf91ab06502fd95397b99b2b858798fbab9151f5/ruff-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c356e770811858bd20832af696ff6c7e884701115094f427b64b25093d6d932d", size = 9942585 }, + { url = "https://files.pythonhosted.org/packages/91/5a/642ed8f1ba23ffc2dd347697e01eef3c42fad6ac76603be4a8c3a9d6311e/ruff-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c0a60a825e3e177116c84009d5ebaa90cf40dfab56e1358d1df4e29a9a14b13", size = 10797597 }, + { url = "https://files.pythonhosted.org/packages/30/25/2e654bc7226da09a49730a1a2ea6e89f843b362db80b4b2a7a4f948ac986/ruff-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fb782f4db39501210ac093c79c3de581d306624575eddd7e4e13747e61ba18", size = 10307244 }, + { url = "https://files.pythonhosted.org/packages/c0/2d/a224d56bcd4383583db53c2b8f410ebf1200866984aa6eb9b5a70f04e71f/ruff-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f26bc76a133ecb09a38b7868737eded6941b70a6d34ef53a4027e83913b6502", size = 11362439 }, + { url = "https://files.pythonhosted.org/packages/82/01/03e2857f9c371b8767d3e909f06a33bbdac880df17f17f93d6f6951c3381/ruff-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:01b14b2f72a37390c1b13477c1c02d53184f728be2f3ffc3ace5b44e9e87b90d", size = 12078538 }, + { url = "https://files.pythonhosted.org/packages/af/ae/ff7f97b355da16d748ceec50e1604a8215d3659b36b38025a922e0612e9b/ruff-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53babd6e63e31f4e96ec95ea0d962298f9f0d9cc5990a1bbb023a6baf2503a82", size = 11616172 }, + { url = "https://files.pythonhosted.org/packages/6a/d0/6156d4d1e53ebd17747049afe801c5d7e3014d9b2f398b9236fe36ba4320/ruff-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ae441ce4cf925b7f363d33cd6570c51435972d697e3e58928973994e56e1452", size = 12919886 }, + { url = "https://files.pythonhosted.org/packages/4e/84/affcb30bacb94f6036a128ad5de0e29f543d3f67ee42b490b17d68e44b8a/ruff-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c65bc0cadce32255e93c57d57ecc2cca23149edd52714c0c5d6fa11ec328cd", size = 11212599 }, + { url = "https://files.pythonhosted.org/packages/60/b9/5694716bdefd8f73df7c0104334156c38fb0f77673d2966a5a1345bab94d/ruff-0.8.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5be450bb18f23f0edc5a4e5585c17a56ba88920d598f04a06bd9fd76d324cb20", size = 10784637 }, + { url = "https://files.pythonhosted.org/packages/24/7e/0e8f835103ac7da81c3663eedf79dec8359e9ae9a3b0d704bae50be59176/ruff-0.8.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8faeae3827eaa77f5721f09b9472a18c749139c891dbc17f45e72d8f2ca1f8fc", size = 10390591 }, + { url = "https://files.pythonhosted.org/packages/27/da/180ec771fc01c004045962ce017ca419a0281f4bfaf867ed0020f555b56e/ruff-0.8.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:db503486e1cf074b9808403991663e4277f5c664d3fe237ee0d994d1305bb060", size = 10894298 }, + { url = "https://files.pythonhosted.org/packages/6d/f8/29f241742ed3954eb2222314b02db29f531a15cab3238d1295e8657c5f18/ruff-0.8.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6567be9fb62fbd7a099209257fef4ad2c3153b60579818b31a23c886ed4147ea", size = 11275965 }, + { url = "https://files.pythonhosted.org/packages/79/e9/5b81dc9afc8a80884405b230b9429efeef76d04caead904bd213f453b973/ruff-0.8.3-py3-none-win32.whl", hash = "sha256:19048f2f878f3ee4583fc6cb23fb636e48c2635e30fb2022b3a1cd293402f964", size = 8807651 }, + { url = "https://files.pythonhosted.org/packages/ea/67/7291461066007617b59a707887b90e319b6a043c79b4d19979f86b7a20e7/ruff-0.8.3-py3-none-win_amd64.whl", hash = "sha256:f7df94f57d7418fa7c3ffb650757e0c2b96cf2501a0b192c18e4fb5571dfada9", size = 9625289 }, + { url = "https://files.pythonhosted.org/packages/03/8f/e4fa95288b81233356d9a9dcaed057e5b0adc6399aa8fd0f6d784041c9c3/ruff-0.8.3-py3-none-win_arm64.whl", hash = "sha256:fe2756edf68ea79707c8d68b78ca9a58ed9af22e430430491ee03e718b5e4936", size = 9078754 }, ] [[package]] @@ -4875,11 +4910,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.7.0" +version = "75.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ac/57/e6f0bde5a2c333a32fbcce201f906c1fd0b3a7144138712a5e9d9598c5ec/setuptools-75.7.0.tar.gz", hash = "sha256:886ff7b16cd342f1d1defc16fc98c9ce3fde69e087a4e1983d7ab634e5f41f4f", size = 1338616 } +sdist = { url = "https://files.pythonhosted.org/packages/43/54/292f26c208734e9a7f067aea4a7e282c080750c4546559b58e2e45413ca0/setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6", size = 1337429 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/6e/abdfaaf5c294c553e7a81cf5d801fbb4f53f5c5b6646de651f92a2667547/setuptools-75.7.0-py3-none-any.whl", hash = "sha256:84fb203f278ebcf5cd08f97d3fb96d3fbed4b629d500b29ad60d11e00769b183", size = 1224467 }, + { url = "https://files.pythonhosted.org/packages/55/21/47d163f615df1d30c094f6c8bbb353619274edccf0327b185cc2493c2c33/setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d", size = 1224032 }, ] [[package]] @@ -5028,7 +5063,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ @@ -5067,11 +5102,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.3.0" +version = "2.2.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, ] [[package]]