This commit is contained in:
HailoRT-Automation
2022-06-30 17:21:15 +03:00
parent dd37bf9936
commit 3506da8c3f
242 changed files with 12308 additions and 9874 deletions

BIN
.hailort.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

212
.logo.svg
View File

@@ -1,212 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4986"
version="1.1"
inkscape:version="0.91 r13725"
xml:space="preserve"
width="454.94739"
height="132.55138"
viewBox="0 0 454.94739 132.55138"
sodipodi:docname="Hailo_Logo_RGB.svg"><metadata
id="metadata4992"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4990"><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5014"><path
d="M 0,110 370,110 370,0 0,0 0,110 Z"
id="path5016"
inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2048"
inkscape:window-height="1100"
id="namedview4988"
showgrid="false"
inkscape:zoom="2.9109866"
inkscape:cx="216.90465"
inkscape:cy="59.262279"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g4994"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><g
id="g4994"
inkscape:groupmode="layer"
inkscape:label="Hailo_Logo_RGB"
transform="matrix(1.25,0,0,-1.25,-5.127625,136.24475)"><g
id="g4996"
transform="translate(172.3149,50.2915)"><path
d="M 0,0 -14.161,0 -40.557,47.98 -40.674,48.181 -40.793,47.98 -67.189,0 -81.35,0 l 34.496,58.684 -0.011,0.02 0.023,0 12.334,0 0.023,0 -0.011,-0.02 L 0,0 Z"
style="fill:#0098c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path4998"
inkscape:connector-curvature="0" /></g><path
d="m 186.287,50.291 14.16,0 0,58.704 -14.16,0 0,-58.704 z"
style="fill:#0098c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5000"
inkscape:connector-curvature="0" /><g
id="g5002"
transform="translate(4.2656,50.2915)"><path
d="m 0,0 14.298,0 0,24.747 44.268,0 0,-24.747 14.161,0 0,58.704 -14.161,0 0,-22.272 -44.268,0 0,22.272 L 0,58.704 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5004"
inkscape:connector-curvature="0" /></g><g
id="g5006"
transform="translate(221.0957,50.2915)"><path
d="m 0,0 59.941,0 0,10.999 -45.643,0 0,47.705 L 0,58.704 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5008"
inkscape:connector-curvature="0" /></g><g
id="g5010"><g
id="g5012"
clip-path="url(#clipPath5014)"><g
id="g5018"
transform="translate(368.06,64.1768)"><path
d="m 0,0 0,30.933 c 0,11.274 -3.712,13.886 -15.123,13.886 l -44.956,0 c -11.411,0 -15.123,-2.612 -15.123,-13.886 l 0,-30.933 c 0,-11.136 3.575,-13.885 15.123,-13.885 l 44.956,0 C -3.712,-13.885 0,-11.136 0,0 m -14.16,-2.612 -46.881,0 0,36.569 46.881,0 0,-36.569 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5020"
inkscape:connector-curvature="0" /></g><g
id="g5022"
transform="translate(15.4511,10.2974)"><path
d="m 0,0 0.106,-1.816 c -1.637,-0.106 -4.272,-0.16 -7.903,-0.16 -1.086,0 -1.945,0.289 -2.577,0.868 -0.632,0.578 -0.957,1.357 -0.975,2.337 l 0,12.068 c 0.018,0.979 0.343,1.758 0.975,2.337 0.632,0.578 1.491,0.867 2.577,0.867 3.631,0 6.266,-0.053 7.903,-0.16 L 0,14.499 l -7.396,0 c -1.069,0 -1.603,-0.587 -1.603,-1.762 l 0,-4.006 7.957,0 0,-1.896 -7.957,0 0,-5.046 C -8.999,0.596 -8.465,0 -7.396,0 L 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5024"
inkscape:connector-curvature="0" /></g><g
id="g5026"
transform="translate(23.7817,21.3521)"><path
d="m 0,0 0.134,-2.056 c 1.833,1.584 3.604,2.376 5.313,2.376 1.816,0 2.911,-0.765 3.284,-2.296 1.763,1.531 3.507,2.296 5.234,2.296 1.121,0 1.98,-0.303 2.577,-0.907 0.596,-0.606 0.895,-1.496 0.895,-2.671 l 0,-9.746 -2.244,0 0,9.106 c -0.018,0.8 -0.182,1.383 -0.494,1.748 -0.311,0.365 -0.823,0.547 -1.535,0.547 -0.623,0 -1.224,-0.142 -1.802,-0.426 -0.579,-0.285 -1.402,-0.82 -2.47,-1.603 l 0,-9.372 -2.19,0 0,9.106 c 0,0.818 -0.164,1.405 -0.494,1.762 C 5.879,-1.78 5.367,-1.603 4.673,-1.603 4.05,-1.603 3.449,-1.745 2.871,-2.029 2.292,-2.314 1.469,-2.84 0.401,-3.605 l 0,-9.399 -2.27,0 L -1.869,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5028"
inkscape:connector-curvature="0" /></g><g
id="g5030"
transform="translate(50.1899,17.6938)"><path
d="m 0,0 0,-6.889 c 1.815,-0.534 3.204,-0.801 4.166,-0.801 1.174,0 1.993,0.329 2.456,0.988 0.462,0.658 0.694,1.922 0.694,3.791 0,1.816 -0.218,3.089 -0.654,3.819 C 6.226,1.637 5.482,2.002 4.432,2.002 3.755,2.002 3.084,1.847 2.417,1.535 1.749,1.224 0.943,0.711 0,0 m -0.401,3.658 0.187,-2.083 c 0.694,0.748 1.531,1.335 2.51,1.762 0.979,0.428 1.94,0.642 2.884,0.642 1.549,0 2.679,-0.57 3.391,-1.709 0.712,-1.14 1.068,-2.867 1.068,-5.181 0,-2.456 -0.391,-4.196 -1.175,-5.22 -0.783,-1.024 -2.029,-1.535 -3.738,-1.535 -1.709,0 -3.311,0.445 -4.806,1.335 C -0.027,-8.937 0,-9.809 0,-10.948 l 0,-3.765 -2.27,0 0,18.371 1.869,0 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5032"
inkscape:connector-curvature="0" /></g><g
id="g5034"
transform="translate(74.581,18.7085)"><path
d="m 0,0 c -0.543,0.694 -1.526,1.041 -2.95,1.041 -1.425,0 -2.404,-0.347 -2.938,-1.041 -0.534,-0.694 -0.8,-1.985 -0.8,-3.872 0,-1.887 0.266,-3.177 0.8,-3.872 0.534,-0.694 1.513,-1.041 2.938,-1.041 1.424,0 2.407,0.347 2.95,1.041 0.543,0.695 0.814,1.985 0.814,3.872 C 0.814,-1.985 0.543,-0.694 0,0 m -2.95,2.964 c 2.242,0 3.822,-0.517 4.739,-1.549 0.917,-1.033 1.375,-2.795 1.375,-5.287 0,-2.492 -0.458,-4.254 -1.375,-5.287 -0.917,-1.032 -2.497,-1.549 -4.739,-1.549 -2.226,0 -3.801,0.517 -4.727,1.549 -0.926,1.033 -1.388,2.795 -1.388,5.287 0,2.492 0.462,4.254 1.388,5.287 0.926,1.032 2.501,1.549 4.727,1.549"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5036"
inkscape:connector-curvature="0" /></g><g
id="g5038"
transform="translate(103.165,21.3521)"><path
d="m 0,0 -3.792,-12.363 c -0.106,-0.428 -0.4,-0.641 -0.881,-0.641 l -2.056,0 c -0.213,0 -0.405,0.067 -0.574,0.2 -0.169,0.134 -0.271,0.307 -0.307,0.521 l -2.136,8.838 c -0.053,0.249 -0.125,0.601 -0.213,1.055 -0.09,0.454 -0.161,0.787 -0.214,1.001 l -0.321,0 -0.454,-2.056 -2.109,-8.838 c -0.125,-0.481 -0.427,-0.721 -0.908,-0.721 l -2.029,0 c -0.481,0 -0.775,0.213 -0.881,0.641 L -20.667,0 l 2.35,0 2.697,-9.586 c 0.16,-0.552 0.302,-1.202 0.427,-1.949 l 0.347,0 0.481,1.949 2.162,8.865 c 0.089,0.48 0.374,0.721 0.855,0.721 l 2.056,0 c 0.445,0 0.729,-0.25 0.854,-0.748 l 2.137,-8.838 c 0.035,-0.196 0.106,-0.512 0.213,-0.948 0.107,-0.436 0.187,-0.77 0.24,-1.001 l 0.348,0 c 0.017,0.089 0.075,0.369 0.173,0.841 0.098,0.471 0.191,0.841 0.281,1.108 L -2.35,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5040"
inkscape:connector-curvature="0" /></g><g
id="g5042"
transform="translate(110.2675,15.5044)"><path
d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5044"
inkscape:connector-curvature="0" /></g><g
id="g5046"
transform="translate(133.9511,21.6724)"><path
d="m 0,0 -0.267,-2.136 -0.748,0 c -0.658,0 -1.339,-0.13 -2.042,-0.387 -0.704,-0.259 -1.642,-0.681 -2.817,-1.269 l 0,-9.532 -2.27,0 0,13.004 1.763,0 0.24,-2.056 C -4.13,-0.792 -2.279,0 -0.587,0 L 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5048"
inkscape:connector-curvature="0" /></g><path
d="m 141.801,8.348 -2.243,0 0,13.004 2.243,0 0,-13.004 z m -1.656,18.531 1.069,0 c 0.462,0 0.694,-0.232 0.694,-0.694 l 0,-1.522 c 0,-0.463 -0.232,-0.694 -0.694,-0.694 l -1.069,0 c -0.462,0 -0.694,0.231 -0.694,0.694 l 0,1.522 c 0,0.462 0.232,0.694 0.694,0.694"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5050"
inkscape:connector-curvature="0" /><g
id="g5052"
transform="translate(150.6127,21.3521)"><path
d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5054"
inkscape:connector-curvature="0" /></g><g
id="g5056"
transform="translate(169.25,15.6777)"><path
d="m 0,0 c 0.516,-0.365 1.415,-0.547 2.697,-0.547 1.282,0 2.18,0.182 2.697,0.547 0.516,0.365 0.774,0.983 0.774,1.856 0,0.872 -0.254,1.491 -0.761,1.855 C 4.899,4.076 3.996,4.259 2.697,4.259 1.415,4.259 0.516,4.076 0,3.711 -0.517,3.347 -0.774,2.728 -0.774,1.856 -0.774,0.983 -0.517,0.365 0,0 M 4.593,-6.715 0.16,-6.101 c -0.908,-0.694 -1.362,-1.523 -1.362,-2.483 0,-0.908 0.267,-1.504 0.801,-1.79 0.534,-0.284 1.611,-0.427 3.231,-0.427 1.585,0 2.648,0.147 3.191,0.441 0.543,0.294 0.814,0.885 0.814,1.776 0,0.64 -0.138,1.077 -0.413,1.308 -0.276,0.231 -0.886,0.418 -1.829,0.561 M 9.666,4.419 7.743,4.259 C 8.099,3.671 8.277,2.871 8.277,1.856 8.277,0.396 7.859,-0.659 7.022,-1.309 6.186,-1.958 4.744,-2.283 2.697,-2.283 1.7,-2.283 0.801,-2.194 0,-2.016 c -0.338,-0.41 -0.437,-0.859 -0.294,-1.348 0.143,-0.49 0.543,-0.788 1.202,-0.895 l 4.86,-0.774 c 1.21,-0.178 2.06,-0.557 2.549,-1.135 0.49,-0.579 0.735,-1.419 0.735,-2.523 0,-1.513 -0.45,-2.564 -1.349,-3.151 -0.899,-0.588 -2.514,-0.881 -4.846,-0.881 -2.35,0 -3.983,0.289 -4.9,0.868 -0.917,0.578 -1.375,1.606 -1.375,3.084 0,0.765 0.16,1.379 0.48,1.842 0.321,0.463 0.864,0.899 1.629,1.308 -0.658,0.517 -0.961,1.202 -0.907,2.057 0.053,0.854 0.391,1.522 1.014,2.002 -1.104,0.587 -1.655,1.718 -1.655,3.391 0,1.495 0.414,2.564 1.241,3.204 0.828,0.641 2.274,0.962 4.34,0.962 1.228,0 2.233,-0.107 3.017,-0.321 l 4.058,0 -0.133,-1.255 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5058"
inkscape:connector-curvature="0" /></g><path
d="m 201.456,8.348 -2.35,0 0,18.424 2.35,0 0,-18.424 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5060"
inkscape:connector-curvature="0" /><g
id="g5062"
transform="translate(210.4013,21.3521)"><path
d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5064"
inkscape:connector-curvature="0" /></g><g
id="g5066"
transform="translate(230.08,19.563)"><path
d="M 0,0 0,-7.637 C 0,-8.26 0.133,-8.705 0.4,-8.972 0.667,-9.239 1.122,-9.373 1.762,-9.373 l 1.976,0 0.267,-1.735 c -0.819,-0.231 -1.798,-0.347 -2.937,-0.347 -1.086,0 -1.914,0.302 -2.483,0.908 -0.57,0.605 -0.855,1.477 -0.855,2.616 l 0,7.931 -2.35,0 0,1.655 2.35,0.107 0,3.872 2.27,0 0,-3.845 4.139,0 L 4.139,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5068"
inkscape:connector-curvature="0" /></g><g
id="g5070"
transform="translate(241.455,15.5044)"><path
d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5072"
inkscape:connector-curvature="0" /></g><g
id="g5074"
transform="translate(259.0776,27.0391)"><path
d="m 0,0 0,-15.113 c -0.018,-0.57 0.125,-1.001 0.427,-1.295 0.303,-0.294 0.748,-0.441 1.336,-0.441 l 1.255,0 0.267,-1.735 c -0.481,-0.231 -1.273,-0.347 -2.377,-0.347 -0.979,0 -1.754,0.289 -2.323,0.868 -0.57,0.578 -0.855,1.392 -0.855,2.443 L -2.27,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5076"
inkscape:connector-curvature="0" /></g><g
id="g5078"
transform="translate(269.7314,27.0391)"><path
d="m 0,0 0,-15.113 c -0.018,-0.57 0.125,-1.001 0.427,-1.295 0.303,-0.294 0.748,-0.441 1.336,-0.441 l 1.255,0 0.267,-1.735 c -0.481,-0.231 -1.273,-0.347 -2.377,-0.347 -0.979,0 -1.754,0.289 -2.323,0.868 -0.57,0.578 -0.855,1.392 -0.855,2.443 L -2.27,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5080"
inkscape:connector-curvature="0" /></g><path
d="m 280.546,8.348 -2.243,0 0,13.004 2.243,0 0,-13.004 z m -1.656,18.531 1.068,0 c 0.463,0 0.694,-0.232 0.694,-0.694 l 0,-1.522 c 0,-0.463 -0.231,-0.694 -0.694,-0.694 l -1.068,0 c -0.463,0 -0.694,0.231 -0.694,0.694 l 0,1.522 c 0,0.462 0.231,0.694 0.694,0.694"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5082"
inkscape:connector-curvature="0" /><g
id="g5084"
transform="translate(289.8642,15.6777)"><path
d="m 0,0 c 0.516,-0.365 1.415,-0.547 2.697,-0.547 1.282,0 2.18,0.182 2.697,0.547 0.516,0.365 0.774,0.983 0.774,1.856 0,0.872 -0.254,1.491 -0.761,1.855 C 4.899,4.076 3.996,4.259 2.697,4.259 1.415,4.259 0.516,4.076 0,3.711 -0.517,3.347 -0.774,2.728 -0.774,1.856 -0.774,0.983 -0.517,0.365 0,0 M 4.593,-6.715 0.16,-6.101 c -0.908,-0.694 -1.362,-1.523 -1.362,-2.483 0,-0.908 0.267,-1.504 0.801,-1.79 0.534,-0.284 1.611,-0.427 3.231,-0.427 1.585,0 2.648,0.147 3.191,0.441 0.543,0.294 0.814,0.885 0.814,1.776 0,0.64 -0.138,1.077 -0.413,1.308 -0.276,0.231 -0.886,0.418 -1.829,0.561 M 9.666,4.419 7.743,4.259 C 8.099,3.671 8.277,2.871 8.277,1.856 8.277,0.396 7.859,-0.659 7.022,-1.309 6.186,-1.958 4.744,-2.283 2.697,-2.283 1.7,-2.283 0.801,-2.194 0,-2.016 c -0.338,-0.41 -0.437,-0.859 -0.294,-1.348 0.143,-0.49 0.543,-0.788 1.202,-0.895 l 4.86,-0.774 c 1.21,-0.178 2.06,-0.557 2.549,-1.135 0.49,-0.579 0.735,-1.419 0.735,-2.523 0,-1.513 -0.45,-2.564 -1.349,-3.151 -0.899,-0.588 -2.514,-0.881 -4.846,-0.881 -2.35,0 -3.983,0.289 -4.9,0.868 -0.917,0.578 -1.375,1.606 -1.375,3.084 0,0.765 0.16,1.379 0.48,1.842 0.321,0.463 0.864,0.899 1.629,1.308 -0.658,0.517 -0.961,1.202 -0.907,2.057 0.053,0.854 0.391,1.522 1.014,2.002 -1.104,0.587 -1.655,1.718 -1.655,3.391 0,1.495 0.414,2.564 1.241,3.204 0.828,0.641 2.274,0.962 4.34,0.962 1.228,0 2.233,-0.107 3.017,-0.321 l 4.058,0 -0.133,-1.255 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5086"
inkscape:connector-curvature="0" /></g><g
id="g5088"
transform="translate(306.7929,15.5044)"><path
d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5090"
inkscape:connector-curvature="0" /></g><g
id="g5092"
transform="translate(323.935,21.3521)"><path
d="m 0,0 0.16,-2.056 c 2.1,1.584 4.041,2.376 5.821,2.376 2.35,0 3.525,-1.193 3.525,-3.578 l 0,-9.746 -2.27,0 0,9.106 c 0,0.854 -0.143,1.45 -0.427,1.788 -0.285,0.339 -0.766,0.507 -1.442,0.507 -0.712,0 -1.429,-0.16 -2.15,-0.48 -0.72,-0.32 -1.677,-0.846 -2.87,-1.575 l 0,-9.346 -2.27,0 L -1.923,0 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5094"
inkscape:connector-curvature="0" /></g><g
id="g5096"
transform="translate(349.7817,10.2173)"><path
d="m 0,0 0.241,-1.522 c -1.282,-0.445 -2.769,-0.667 -4.46,-0.667 -2.242,0 -3.831,0.511 -4.766,1.535 -0.934,1.023 -1.402,2.79 -1.402,5.3 0,2.51 0.468,4.272 1.402,5.287 0.935,1.015 2.532,1.522 4.793,1.522 1.709,0 3.106,-0.205 4.192,-0.614 L -0.293,9.372 c -1.175,0.107 -2.35,0.16 -3.525,0.16 -1.567,0 -2.653,-0.346 -3.258,-1.041 -0.605,-0.694 -0.907,-1.976 -0.907,-3.845 0,-1.887 0.302,-3.177 0.907,-3.872 0.605,-0.694 1.691,-1.041 3.258,-1.041 1.424,0 2.697,0.089 3.818,0.267"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5098"
inkscape:connector-curvature="0" /></g><g
id="g5100"
transform="translate(357.125,15.5044)"><path
d="M 0,0 5.5,0 C 6.444,0 6.916,0.641 6.916,1.922 6.898,2.759 6.649,3.355 6.168,3.711 5.687,4.067 4.869,4.245 3.711,4.245 2.34,4.245 1.389,3.947 0.854,3.351 0.32,2.754 0.036,1.637 0,0 m 6.088,-1.763 -6.061,0 c 0.124,-1.495 0.489,-2.501 1.095,-3.017 0.605,-0.516 1.61,-0.774 3.017,-0.774 1.477,0 2.981,0.107 4.512,0.32 l 0.241,-1.522 c -1.158,-0.48 -2.84,-0.721 -5.047,-0.721 -2.243,0 -3.841,0.521 -4.793,1.562 -0.952,1.042 -1.428,2.808 -1.428,5.301 0,2.51 0.462,4.267 1.388,5.273 0.926,1.006 2.457,1.509 4.592,1.509 C 5.545,6.168 6.96,5.816 7.85,5.113 8.74,4.41 9.186,3.346 9.186,1.922 9.221,-0.534 8.188,-1.763 6.088,-1.763"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path5102"
inkscape:connector-curvature="0" /></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,11 +1,13 @@
cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYBIND "Build Python binding" OFF)
option(HAILO_BUILD_PYHAILORT_VENV "Build pyhailort in venv" ON)
option(HAILO_BUILD_PYHAILORT_VENV "Build pyhailort in venv. Only used if HAILO_BUILD_PYBIND is on" ON)
option(HAILO_BUILD_EMULATOR "Build hailort for emulator" OFF)
option(HAILO_BUILD_UT "Build Unit Tests" OFF)
option(HAILO_BUILD_GSTREAMER "Compile gstreamer plugins" OFF)
option(HAILO_BUILD_EXAMPLES "Build examples" OFF)
option(HAILO_OFFLINE_COMPILATION "Don't download external dependencies" OFF)
option(HAILO_MICROPROFILE "Microprofile code" OFF)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
@@ -14,6 +16,13 @@ endif()
project(HailoRT)
# Prevent in-tree building
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source builds are not allowed.
Please remove the `CMakeCache.txt` file and `CMakeFiles` directory from `${CMAKE_SOURCE_DIR}`
In order to build, please create a new `build` directory and run `cmake ..` from there.")
endif()
# Check build type
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Debug")
@@ -35,20 +44,8 @@ if(WIN32)
/wd4251 # C++ ABI with STL
)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Disable "unsafe function" warnings
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} /O2 /DNDEBUG /Zi)
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} /Od /Zi /DDEBUG)
else()
message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
endif()
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")
elseif(UNIX)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "QCC")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra -Wconversion)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -Werror -Wall -Wextra
@@ -60,14 +57,6 @@ elseif(UNIX)
else()
message(FATAL_ERROR "Invalid value for CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}")
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -O3 -DNDEBUG)
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -O0 -g -DDEBUG)
else()
message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
endif()
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
@@ -80,23 +69,8 @@ if(HAILO_BUILD_EMULATOR)
set(HAILORT_COMPILE_OPTIONS ${HAILORT_COMPILE_OPTIONS} -DHAILO_EMULATOR)
endif()
# Prevent in-tree building
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source builds are not allowed.
Please remove the `CMakeCache.txt` file and `CMakeFiles` directory from `${CMAKE_SOURCE_DIR}`
In order to build, please create a new `build` directory and run `cmake ..` from there.")
endif()
# Enable output of compile commands during generation
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Set validation dir
set(PLATFORM_VALIDATION_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/platform_internals/hailo_platform_internals/validation")
if (NOT DEFINED HEFS_DIR)
set(HEFS_DIR "${PLATFORM_VALIDATION_DIRECTORY}/hefs/latest")
message(STATUS "No HEFS_DIR provided, using default ('${HEFS_DIR}')")
endif()
# Add subdirectories
add_subdirectory(hailort)

View File

@@ -1,5 +1,5 @@
<p align="left">
<img src=".logo.svg" />
<img src=".hailort.png" />
</p>

View File

@@ -23,7 +23,6 @@ extern "C" {
#define CONTEXT_SWITCH_DEFS__TIMESTAMP_INIT_VALUE (0xFFFFFFFF)
#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_ADDRESS (1)
#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_KERNEL_COUNT (2)
#define CONTEXT_SWITCH_DEFS__ENABLE_LCU_DEFAULT_BATCH_SIZE (1)
#define CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_LCU_INDEX_SHIFT (0)
#define CONTEXT_SWITCH_DEFS__PACKED_LCU_ID_LCU_INDEX_WIDTH (4)
@@ -57,7 +56,7 @@ typedef enum : uint8_t {
#else
typedef enum __attribute__((packed)) {
#endif
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS = 0,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS = 0,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_TRIGGER_SEQUENCER,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_DATA_FROM_VDMA_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT,
@@ -85,6 +84,8 @@ typedef enum __attribute__((packed)) {
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_DMA_IDLE_ACTION,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_NMS_IDLE,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CCW_BURSTS,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START,
/* Must be last */
CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT
@@ -116,9 +117,18 @@ typedef struct {
* | | | .last_executed = <last_action_executed_in_repeated>; |
* | | | .sub_action_type = CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT; |
* | | | } |
* | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
* | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
* | V | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { .packed_lcu_id=<some_lcu_id>; } |
* | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
* | | | .packed_lcu_id=<some_lcu_id>; |
* | | | .network_index=<some_network_index> |
* | | | } |
* | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
* | | | .packed_lcu_id=<some_lcu_id>; |
* | | | .network_index=<some_network_index> |
* | | | } |
* | | | CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t { |
* | | | .packed_lcu_id=<some_lcu_id>; |
* | | | .network_index=<some_network_index> |
* | V | } |
* | ... | (Next action starting with CONTEXT_SWITCH_DEFS__common_action_header_t) |
* |-------------------------------------------------------------------------------------------------------|
* See also: "CONTROL_PROTOCOL__REPEATED_ACTION_t" in "control_protocol.h"
@@ -132,7 +142,7 @@ typedef struct {
typedef struct {
uint16_t descriptors_count;
uint8_t cfg_channel_number;
} CONTEXT_SWITCH_DEFS__read_vdma_action_data_t;
} CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t;
typedef struct {
uint16_t ccw_bursts;
@@ -146,6 +156,7 @@ typedef struct {
typedef struct {
uint8_t packed_lcu_id;
uint8_t network_index;
uint16_t kernel_done_address;
uint32_t kernel_done_count;
} CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t;
@@ -153,6 +164,7 @@ typedef struct {
/* Default action - kernel_done_address and kernel_done_count has default values */
typedef struct {
uint8_t packed_lcu_id;
uint8_t network_index;
} CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t;
typedef struct {
@@ -163,14 +175,27 @@ typedef struct {
uint8_t vdma_channel_index;
uint8_t edge_layer_direction;
bool is_inter_context;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t edge_layer_direction;
bool is_inter_context;
bool is_single_context_network_group;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t;
typedef struct {
uint8_t vdma_channel_index;
uint8_t stream_index;
uint32_t channel_credits;
uint8_t network_index;
uint32_t frame_periph_size;
uint8_t credit_type;
uint16_t periph_bytes_per_buffer;
uint8_t host_buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t, relevant only for descriptors credit.
} CONTEXT_SWITCH_DEFS__fetch_data_action_data_t;
typedef struct {
@@ -182,7 +207,8 @@ typedef struct {
typedef struct {
uint8_t h2d_vdma_channel_index;
uint8_t d2h_vdma_channel_index;
uint32_t descriptors_per_batch;
uint8_t network_index;
uint32_t descriptors_per_frame;
uint16_t programmed_descriptors_count;
} CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t;
@@ -227,16 +253,17 @@ typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint32_t initial_credit_size;
bool is_single_context_app;
} CONTEXT_SWITCH_DEFS__activate_boundary_input_data_t;
typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
uint8_t desc_list_depth;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__activate_inter_context_input_data_t;
typedef struct {
@@ -244,9 +271,8 @@ typedef struct {
uint8_t vdma_channel_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
uint8_t desc_list_depth;
bool fw_managed_channel;
uint32_t initial_credit_size;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_input_data_t;
typedef struct {
@@ -260,13 +286,9 @@ typedef struct {
typedef struct {
uint8_t stream_index;
uint8_t vdma_channel_index;
uint8_t network_index;
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
// TODO: add this to CONTEXT_SWITCH_DEFS__stream_reg_info_t
uint32_t frame_credits_in_bytes;
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
uint16_t desc_page_size;
uint8_t desc_list_depth;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_inter_context_output_data_t;
typedef struct {
@@ -275,16 +297,14 @@ typedef struct {
CONTEXT_SWITCH_DEFS__stream_reg_info_t stream_reg_info;
uint32_t frame_credits_in_bytes;
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
uint16_t desc_page_size;
uint8_t desc_list_depth;
bool fw_managed_channel;
uint32_t buffered_rows_count;
} CONTEXT_SWITCH_DEFS__activate_ddr_buffer_output_data_t;
typedef struct {
uint8_t channel_index;
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTEXT_SWITCH_DEFS__activate_cfg_channel_t;
typedef struct {

View File

@@ -59,6 +59,11 @@ extern "C" {
#define CONTROL_PROTOCOL__REQUEST_BASE_SIZE (sizeof(CONTROL_PROTOCOL__request_header_t) + sizeof(uint32_t))
#define CONTROL_PROTOCOL__OPCODE_INVALID 0xFFFFFFFF
/* If a control accepts a dynamic_batch_size and this value is passed, the
* dynamic_batch_size will be ignored. The pre-configured batch_size will be used.
*/
#define CONTROL_PROTOCOL__IGNORE_DYNAMIC_BATCH_SIZE (0)
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_SHIFT (0)
#define CONTROL_PROTOCOL__TRIGGER_SUB_INDEX_BIT_MASK (0x000000FF)
#define CONTROL_PROTOCOL__TRIGGER_INDEX_SHIFT (16)
@@ -862,21 +867,24 @@ typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_VER_V1_0_0 = 0x010000,
} CONTROL_PROTOCOL__CONTEXT_SWITCH_VERSION_t;
typedef struct {
bool is_abbale_supported;
} CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t;
typedef struct {
bool preliminary_run_asap;
} CONTROL_PROTOCOL__INFER_FEATURE_LIST_t;
typedef struct {
uint8_t dynamic_contexts_count;
uint32_t host_boundary_channels_bitmap;
uint32_t host_ddr_channels_bitmap;
uint8_t cfg_channels_count;
uint8_t cfg_channel_numbers[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint8_t power_mode; // CONTROL_PROTOCOL__power_mode_t
CONTROL_PROTOCOL__INFER_FEATURE_LIST_t infer_features;
uint8_t networks_count;
uint16_t batch_size[CONTROL_PROTOCOL__MAX_NETWORKS_PER_NETWORK_GROUP];
} CONTROL_PROTOCOL__application_header_t;
typedef struct {
bool is_abbale_supported;
} CONTROL_PROTOCOL__VALIDATION_FEATURE_LIST_t;
typedef struct {
uint32_t context_switch_version_length;
uint32_t context_switch_version;
@@ -960,6 +968,7 @@ typedef enum {
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ADD_REPEATED,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_FETCH_CCW_BURSTS,
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_BURST_CREDITS_TASK_START,
/* must be last*/
CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_COUNT,
@@ -1026,6 +1035,25 @@ typedef enum {
CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_COUNT
} CONTROL_PROTOCOL__EDGE_CONNECTION_TYPE_t;
typedef enum {
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_EXTERNAL_DESC = 0,
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_CCB,
// The buffer uses external descriptors that is host managed - the firmware don't need to config this buffer
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_HOST_MANAGED_EXTERNAL_DESC,
/* must be last*/
CONTROL_PROTOCOL__HOST_BUFFER_TYPE_COUNT
} CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t;
typedef struct {
uint8_t buffer_type; // CONTROL_PROTOCOL__HOST_BUFFER_TYPE_t
uint64_t dma_address;
uint16_t desc_page_size;
uint32_t total_desc_count;
uint32_t bytes_in_pattern;
} CONTROL_PROTOCOL__host_buffer_info_t;
typedef struct {
uint8_t communication_type;
uint8_t edge_connection_type;
@@ -1040,7 +1068,6 @@ typedef struct {
typedef struct {
uint64_t host_descriptors_base_address;
uint16_t initial_host_available_descriptors;
uint8_t desc_list_depth;
} CONTROL_PROTOCOL__host_desc_address_info_t;
@@ -1052,9 +1079,7 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint32_t frame_credits_in_bytes;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
uint16_t desc_page_size;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
} CONTROL_PROTOCOL__inter_context_output_t;
typedef struct {
@@ -1062,7 +1087,7 @@ typedef struct {
uint32_t frame_credits_in_bytes;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
uint16_t desc_page_size;
bool fw_managed_channel;
uint32_t buffered_rows_count;
} CONTROL_PROTOCOL__ddr_buffer_output_t;
@@ -1073,19 +1098,19 @@ typedef struct {
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
uint16_t desc_page_size;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__network_boundary_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
uint16_t desc_page_size;
uint16_t context_credits_in_descriptors;
CONTROL_PROTOCOL__host_buffer_info_t host_buffer_info;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__inter_context_input_t;
typedef struct {
CONTROL_PROTOCOL__edge_layer_common_info_t common_info;
CONTROL_PROTOCOL__host_desc_address_info_t host_desc_address_info;
bool fw_managed_channel;
uint32_t initial_credit_size;
} CONTROL_PROTOCOL__ddr_buffer_input_t;
typedef struct {
@@ -1106,10 +1131,10 @@ typedef struct {
uint8_t is_first_control_per_context;
uint32_t is_last_control_per_context_length;
uint8_t is_last_control_per_context;
uint32_t context_cfg_base_address_length;
uint64_t context_cfg_base_address[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint32_t context_cfg_total_descriptors_length;
uint16_t context_cfg_total_descriptors[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint32_t cfg_channels_count_length;
uint8_t cfg_channels_count;
uint32_t config_buffer_infos_length;
CONTROL_PROTOCOL__host_buffer_info_t config_buffer_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint32_t context_stream_remap_data_length;
CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
uint32_t number_of_edge_layers_length;
@@ -1155,16 +1180,19 @@ typedef struct {
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | | | } |
* | | | CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t { |
* | | | .header = { CONTROL_PROTOCOL__CONTEXT_SWITCH_ACTION_ENABLE_LCU_DEFAULT, true }; |
* | | | .cluster_index = <some_cluster_index>; |
* | | | .lcu_index = <some_lcu_index>; |
* | | | .network_index = <some_network_index>; |
* | V | } |
* | ... | (Next action control) |
* |--------------------------------------------------------------------------------------------------|
@@ -1236,6 +1264,7 @@ typedef struct {
CONTROL_PROTOCOL__ACTION_HEADER_t header;
uint8_t cluster_index;
uint8_t lcu_index;
uint8_t network_index;
} CONTROL_PROTOCOL__ENABLE_LCU_DEFAULT_ACTION_t;
typedef struct {
@@ -1265,6 +1294,11 @@ typedef struct {
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__ADD_DDR_BUFFERING_START_ACTION_t;
typedef struct {
/* Must be first */
CONTROL_PROTOCOL__ACTION_HEADER_t header;
} CONTROL_PROTOCOL__BURST_CREDITS_TASK_START_ACTION_T;
typedef struct {
CONTROL_PROTOCOL__TRIGGER_t trigger;
uint16_t triggers_action_count;
@@ -1324,6 +1358,8 @@ typedef struct {
uint8_t state_machine_status;
uint32_t application_index_length;
uint8_t application_index;
uint32_t dynamic_batch_size_length;
uint16_t dynamic_batch_size;
} CONTROL_PROTOCOL__change_context_switch_status_request_t;
typedef struct {
@@ -1338,6 +1374,8 @@ typedef struct {
typedef struct {
uint32_t application_index_length;
uint8_t application_index;
uint32_t dynamic_batch_size_length;
uint16_t dynamic_batch_size;
} CONTROL_PROTOCOL__switch_application_request_t;
typedef struct {
@@ -1674,8 +1712,8 @@ typedef struct {
typedef struct {
bool is_first_control_per_context;
bool is_last_control_per_context;
uint64_t context_cfg_base_address[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint16_t context_cfg_total_descriptors[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
uint8_t cfg_channels_count;
CONTROL_PROTOCOL__host_buffer_info_t config_buffer_infos[CONTROL_PROTOCOL__MAX_CFG_CHANNELS];
CONTROL_PROTOCOL__stream_remap_data_t context_stream_remap_data;
uint8_t number_of_edge_layers;
uint8_t number_of_trigger_groups;

View File

@@ -395,6 +395,10 @@ Updating rules:
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_FAILED_SETTING_OVERCURRENT_STATE)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_CONTROL_UNSUPPORTED)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_CONTROL_DEPRECATED)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CONTEXT_SWITCH_HOST_BUFFER_INFO)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_CFG_CHANNELS_COUNT_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_DYNAMIC_BATCH_SIZE_LENGTH)\
FIRMWARE_STATUS__X(CONTROL_PROTOCOL_STATUS_INVALID_INFER_FEATURES_LENGTH) /* DEPRECATED */\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__POWER_MEASUREMENT)\
FIRMWARE_STATUS__X(HAILO_POWER_MEASUREMENT_STATUS_POWER_INIT_ERROR)\
@@ -537,6 +541,7 @@ Updating rules:
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_GLUE_LOGIC_CHANNEL_OUT_OF_RANGE)\
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_INVALID_H2D_CHANNEL_INDEX)\
FIRMWARE_STATUS__X(PCIE_SERVICE_STATUS_INVALID_D2H_CHANNEL_INDEX)\
FIRMWARE_STATUS__X(PCIE_SERVICE_INVALID_INITIAL_CREDIT_SIZE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__FIRMWARE_UPDATE)\
FIRMWARE_STATUS__X(FIRMWARE_UPDATE_STATUS_INVALID_PARAMETERS)\
@@ -726,6 +731,10 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_CLUSTER_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_OUTPUT_BUFFER_INTERFACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_ACTION_IS_NOT_SUPPORTED)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CFG_CHANNELS_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_HOST_BUFFER_TYPE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_BURST_CREDITS_TASK_IS_NOT_IDLE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\
@@ -940,6 +949,7 @@ Updating rules:
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_NOT_ENABLED_WHILE_TRYING_TO_FETCH_CONFIG)\
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_BURST_COUNTER_IS_NOT_ZERO)\
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_CREDIT_COUNTER_IS_NOT_ZERO)\
FIRMWARE_STATUS__X(CSM_CONFIG_MANAGER_STATUS_CSM_FIFO_NOT_EMPTY)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__PCIE_CONFIG_MANAGER)\
FIRMWARE_STATUS__X(PCIE_CONFIG_MANAGER_STATUS_NOT_IMPLEMENTED)\
@@ -964,6 +974,16 @@ Updating rules:
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_NULL_ARG_PASSED)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CHANNEL_FAILED_TO_REACH_IDLE_STATE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_VDMA_MUST_BE_STOPPED_WHEN_CHECKING_IDLE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_EXTERNAL_DESC_COUNT_MUST_BE_POWER_OF_2)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_TOO_MANY_DESCRIPTORS)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_HOST_BUFFER_TYPE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_DESC_PAGE_SIZE_MUST_BE_POWER_OF_2)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INITIAL_DESC_BIGGER_EQ_THAN_TOTAL)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CCB_NOT_IMPLEMENTED_OVER_PCIE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_CCB_BASE_ADDRESS_IS_NOT_IN_MASK)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INITIAL_DESC_BIGGER_THAN_TOTAL)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_INVALID_INITIAL_CREDIT_SIZE)\
FIRMWARE_STATUS__X(VDMA_SERVICE_STATUS_TOO_LARGE_BYTES_IN_PATTERN)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__MEMORY_LOGGER)\
FIRMWARE_STATUS__X(MEMORY_LOGGER_STATUS_DEBUG_INSUFFICIENT_MEMORY)\
@@ -980,6 +1000,13 @@ Updating rules:
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_SETUP_INTERRUPT_HANDLER_FAILED)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_BURST_CREDIT_SIZE_TOO_BIG)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_CHANNEL_DMA_ADDRESS)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_STATUS_INVALID_DESC_PAGE_SIZE)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_NUM_PAGES_IS_OUT_OF_RANGE)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_INVALID_INITIAL_CREDIT_SIZE)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_TOTAL_DESCS_COUNT_IS_OUT_OF_RANGE)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_TOTAL_DESCS_COUNT_MUST_BE_POWER_OF_2)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_INVALID_DESCS_COUNT)\
FIRMWARE_STATUS__X(DRAM_DMA_SERVICE_DESC_PER_INTERRUPT_NOT_IN_MASK)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__NN_CORE_SERVICE)\
FIRMWARE_STATUS__X(NN_CORE_SERVICE_STATUS_INVALID_ARG_PASSED)\
@@ -989,6 +1016,19 @@ Updating rules:
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_EDGE_LAYER_INDEX)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_DESC_PAGE_SIZE)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_EDGE_LAYER_DIRECTION)\
FIRMWARE_STATUS__X(DATA_STREAM_WRAPPER_STATUS_INVALID_CHANNEL_INDEX)\
FIRMWARE_STATUS__X(DATA_STREAM_WRAPPER_STATUS_INVALID_STREAM_INDEX)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_STATUS_INVALID_CREDIT_TYPE)\
FIRMWARE_STATUS__X(DATA_STREAM_MANAGER_WRAPPER_STATUS_INVALID_HOST_BUFFER_TYPE)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__BURST_CREDITS_TASK)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TRYING_TO_ADD_ACTION_WHILE_NOT_IN_IDLE_STATE)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TOO_MANY_ACTIONS)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TRYING_TO_CHANGE_STATE_TO_INFER_WHILE_ALREADY_IN_INFER)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_INFER_REACHED_TIMEOUT)\
FIRMWARE_STATUS__X(BURST_CREDITS_TASK_STATUS_TASK_DEACTIVATED)\
\
typedef enum {
#define FIRMWARE_MODULE__X(module) module,

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
add_definitions( -DFIRMWARE_VERSION_MINOR=6 )
add_definitions( -DFIRMWARE_VERSION_MINOR=8 )
add_definitions( -DFIRMWARE_VERSION_REVISION=0 )
message(STATUS "Building pre_build")
@@ -15,6 +15,7 @@ execute_cmake(
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_LIST_DIR}/pre_build/install
-DHAILO_EXTERNAL_DIR=${HAILO_EXTERNAL_DIR}
-DHAILO_OFFLINE_COMPILATION=${HAILO_OFFLINE_COMPILATION}
BUILD_ARGS
--config ${CMAKE_BUILD_TYPE} --target install ${CMAKE_EXTRA_BUILD_ARGS}
PARALLEL_BUILD
@@ -61,6 +62,17 @@ set(COMMON_INC_DIR ${PROJECT_SOURCE_DIR}/common/include)
set(DRIVER_INC_DIR ${PROJECT_SOURCE_DIR}/hailort/drivers/common)
if(HAILO_BUILD_PYBIND)
if(NOT PYTHON_EXECUTABLE AND PYBIND11_PYTHON_VERSION)
# PYBIND11_PYTHON_VERSION is prioritized (not virtual environment) if PYTHON_EXECUTABLE is not set.
# See https://pybind11.readthedocs.io/en/stable/changelog.html#v2-6-0-oct-21-2020
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
find_package(PythonInterp ${PYBIND11_PYTHON_VERSION} REQUIRED)
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
else()
find_package(Python3 ${PYBIND11_PYTHON_VERSION} REQUIRED EXACT COMPONENTS Interpreter Development)
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
endif()
endif()
add_subdirectory(external/pybind11 EXCLUDE_FROM_ALL)
endif()
add_subdirectory(external/Catch2 EXCLUDE_FROM_ALL)
@@ -69,28 +81,39 @@ add_subdirectory(external/json EXCLUDE_FROM_ALL)
add_subdirectory(external/DotWriter EXCLUDE_FROM_ALL)
add_subdirectory(external/spdlog EXCLUDE_FROM_ALL)
set_target_properties(spdlog PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(CMAKE_SYSTEM_NAME STREQUAL QNX)
add_library(pevents STATIC EXCLUDE_FROM_ALL external/pevents/src/pevents.cpp)
target_include_directories(pevents PUBLIC external/pevents/src)
target_compile_definitions(pevents PRIVATE -DWFMO)
endif()
# microprofile
if(HAILO_MICROPROFILE)
add_library(microprofile STATIC EXCLUDE_FROM_ALL external/microprofile/microprofile.cpp)
set_target_properties(microprofile PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
POSITION_INDEPENDENT_CODE ON
)
target_compile_definitions(microprofile
PRIVATE
-DMICROPROFILE_WEBSERVER=1
-DMICROPROFILE_GPU_TIMERS=0
-DMICROPROFILE_NAME_MAX_LEN=256
PUBLIC
-DMICROPROFILE_ENABLED=1
)
target_include_directories(microprofile PUBLIC external/microprofile)
else()
add_library(microprofile INTERFACE)
target_compile_definitions(microprofile INTERFACE -DMICROPROFILE_ENABLED=0)
target_include_directories(microprofile INTERFACE external/microprofile)
endif()
add_subdirectory(common)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
# copy files to venv
if(HAILO_BUILD_PYBIND AND HAILO_BUILD_PYHAILORT_VENV)
set(VENV_DRIVERS_DIR ${CMAKE_SOURCE_DIR}/hailort/libhailort/bindings/python/platform/hailo_platform/drivers/hailort/)
set(PYHAILORT_FILES_TO_COPY
$<TARGET_FILE:_pyhailort>
)
set(VENV_PYHAILORT_INTERNAL_DIR ${CMAKE_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/)
set(PYHAILORT_INTERNAL_FILES_TO_COPY
$<TARGET_FILE:_pyhailort_internal>
)
add_custom_target(
pyhailort_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy ${PYHAILORT_FILES_TO_COPY} ${VENV_DRIVERS_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${PYHAILORT_INTERNAL_FILES_TO_COPY} ${VENV_PYHAILORT_INTERNAL_DIR}
)
add_dependencies(pyhailort_venv libhailort _pyhailort)
endif()
if(HAILO_WIN_DRIVER)
add_subdirectory(drivers/win)
add_subdirectory(packaging)

View File

@@ -3,7 +3,7 @@
| CLI11 | University of Cincinnati | 3-Clause BSD | 1.7 | Cloned entire package | https://github.com/CLIUtils/CLI11 |
| Catch2 | Catch2 Authors | BSL-1.0 | 2.13.7 | Cloned entire package | https://github.com/catchorg/Catch2 |
| protobuf | Google Inc. | BSD | 3.11.4 | Cloned entire package | https://github.com/protocolbuffers/protobuf |
| pybind11 | Wenzel Jakob | BSD | 2.3.0 | Cloned entire package | https://github.com/pybind/pybind11 |
| pybind11 | Wenzel Jakob | BSD | 2.6.2 | Cloned entire package | https://github.com/pybind/pybind11 |
| spdlog | Gabi Melman | MIT | 1.6.1 | Cloned entire package | https://github.com/gabime/spdlog |
| folly | Facebook, Inc. and its affiliates | Apache License 2.0 | v2020.08.17.00 | Copied only the file `folly/TokenBucket.h` | https://github.com/facebook/folly |
| nlohmann_json_cmake_fetchcontent | ArthurSonzogni | MIT License | v3.9.1 | Cloned entire package | https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent |
@@ -11,3 +11,5 @@
| DotWriter | John Vilk | MIT License | master | Cloned entire package (forked) | https://github.com/jvilk/DotWriter |
| benchmark | Google Inc. | Apache License 2.0 | 1.6.0 | Cloned entire package | https://github.com/google/benchmark.git |
| md5 | Alexander Peslyak | cut-down BSD | - | Copied code from website | http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 |
| pevents | Mahmoud Al-Qudsi | MIT License | master | Cloned entire package | https://github.com/neosmart/pevents.git |
| microprofile | Jonas Meyer | Unlicense License | 3.1 | Cloned entire package | https://github.com/jonasmr/microprofile |

View File

@@ -97,6 +97,11 @@ public:
return CB_HEAD(m_circ) == CB_TAIL(m_circ);
}
bool full()
{
return 0 == CB_AVAIL(m_circ, CB_HEAD(m_circ), CB_TAIL(m_circ));
}
private:
circbuf_t m_circ;
std::vector<T> m_array;

View File

@@ -125,6 +125,7 @@ private:
};
using LatencyMeterPtr = std::shared_ptr<LatencyMeter>;
using LatencyMetersMap = std::map<std::string, LatencyMeterPtr>;
} /* namespace hailort */

View File

@@ -52,7 +52,7 @@ dirent* Filesystem::DirWalker::next_file()
return readdir(m_dir);
}
#if defined(__unix__)
#if defined(__linux__)
Expected<std::vector<std::string>> Filesystem::get_files_in_dir_flat(const std::string &dir_path)
{

View File

@@ -52,6 +52,24 @@ static inline bool contains(const std::set<T> &container, T value)
return (container.find(value) != container.end());
}
template <class T>
class unlock_guard {
public:
unlock_guard(T &lock) : m_lock(lock) {
m_lock.unlock();
}
~unlock_guard() {
m_lock.lock();
}
unlock_guard(const unlock_guard&) = delete;
unlock_guard& operator=(const unlock_guard&) = delete;
private:
T &m_lock;
};
// From https://stackoverflow.com/questions/57092289/do-stdmake-shared-and-stdmake-unique-have-a-nothrow-version
template <class T, class... Args>
static inline std::unique_ptr<T> make_unique_nothrow(Args&&... args)
@@ -241,6 +259,18 @@ constexpr uint32_t get_nearest_powerof_2(uint32_t value, uint32_t min_power_of_2
return power_of_2;
}
template<class K, class V>
static uint32_t get_max_value_of_unordered_map(const std::unordered_map<K, V> &map)
{
uint32_t max_count = 0;
for (auto &name_counter_pair : map) {
if (name_counter_pair.second > max_count) {
max_count = name_counter_pair.second;
}
}
return max_count;
}
} /* namespace hailort */
#endif /* HAILO_UTILS_H_ */

View File

@@ -29,11 +29,13 @@
#ifdef _MSC_VER
#if !defined(bool) && !defined(__cplusplus)
typedef uint8_t bool;
#endif
#endif // !defined(bool) && !defined(__cplusplus)
#if !defined(INT_MAX)
#define INT_MAX 0x7FFFFFFF
#endif
#else
#endif // !defined(INT_MAX)
#elif defined(__linux__) // #ifdef _MSC_VER
#ifndef __KERNEL__
// include the userspace headers only if this file is included by user space program
// It is discourged to include them when compiling the driver (https://lwn.net/Articles/113349/)
@@ -43,11 +45,9 @@ typedef uint8_t bool;
#include <linux/types.h>
#include <linux/limits.h>
#include <linux/kernel.h>
#endif
#endif // ifndef __KERNEL__
#if defined(__unix__)
#include <linux/ioctl.h>
#endif
#define _IOW_ _IOW
#define _IOR_ _IOR
@@ -57,6 +57,21 @@ typedef uint8_t bool;
#define HAILO_GENERAL_IOCTL_MAGIC 'g'
#define HAILO_VDMA_IOCTL_MAGIC 'v'
#define HAILO_WINDOWS_IOCTL_MAGIC 'w'
#elif defined(__QNX__) // #ifdef _MSC_VER
#include <devctl.h>
#include <stdint.h>
#include <sys/types.h>
// defines for devctl
#define _IOW_ __DIOF
#define _IOR_ __DIOT
#define _IOWR_ __DIOTF
#define _IO_ __DION
#define HAILO_GENERAL_IOCTL_MAGIC _DCMD_ALL
#define HAILO_VDMA_IOCTL_MAGIC _DCMD_MISC
#else // #ifdef _MSC_VER
#error "unsupported platform!"
#endif
#pragma pack(push, 1)
@@ -181,6 +196,9 @@ struct hailo_fw_control {
};
/* structure used in ioctl HAILO_BAR_TRANSFER */
// Max bar transfer size gotten from ATR0_TABLE_SIZE
#define MAX_BAR_TRANSFER_LENGTH (4096)
enum hailo_transfer_direction {
TRANSFER_READ = 0,
TRANSFER_WRITE,
@@ -194,7 +212,7 @@ struct hailo_bar_transfer_params {
uint32_t bar_index; // in
off_t offset; // in
size_t count; // in
void* buffer; // in/out
uint8_t buffer[MAX_BAR_TRANSFER_LENGTH]; // in/out
};
/* structure used in ioctl HAILO_VDMA_CHANNEL_REGISTERS */
@@ -222,9 +240,11 @@ struct hailo_vdma_buffer_sync_params {
};
/* structure used in ioctl HAILO_READ_NOTIFICATION */
#define MAX_NOTIFICATION_LENGTH (1500)
struct hailo_d2h_notification {
size_t buffer_len; // out
uint8_t buffer[MAX_CONTROL_LENGTH]; // out
uint8_t buffer[MAX_NOTIFICATION_LENGTH]; // out
};
enum hailo_board_type {
@@ -254,14 +274,18 @@ struct hailo_driver_info {
uint32_t minor_version;
uint32_t revision_version;
};
/* structure used in ioctl HAILO_READ_LOG */
#define MAX_FW_LOG_BUFFER_LENGTH (512)
struct hailo_read_log_params {
enum hailo_cpu_id cpu_id; // in
uint8_t *buffer; // out
uint8_t buffer[MAX_FW_LOG_BUFFER_LENGTH]; // out
size_t buffer_size; // in
size_t read_bytes; // out
};
struct hailo_allocate_buffer_params {
struct hailo_allocate_low_memory_buffer_params {
size_t buffer_size; // in
uintptr_t buffer_handle; // out
};
@@ -270,6 +294,12 @@ struct hailo_mark_as_in_use_params {
bool in_use; // out
};
struct hailo_allocate_continuous_buffer_params {
size_t buffer_size; // in
uintptr_t buffer_handle; // out
uint64_t dma_address; // out
};
#pragma pack(pop)
enum hailo_general_ioctl_code {
@@ -286,7 +316,7 @@ enum hailo_general_ioctl_code {
HAILO_GENERAL_IOCTL_MAX_NR,
};
#define HAILO_BAR_TRANSFER _IOW_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_BAR_TRANSFER_CODE, struct hailo_bar_transfer_params)
#define HAILO_BAR_TRANSFER _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_BAR_TRANSFER_CODE, struct hailo_bar_transfer_params)
#define HAILO_FW_CONTROL _IOWR_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_FW_CONTROL_CODE, struct hailo_fw_control)
#define HAILO_READ_NOTIFICATION _IOW_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_READ_NOTIFICATION_CODE, struct hailo_d2h_notification)
#define HAILO_DISABLE_NOTIFICATION _IO_(HAILO_GENERAL_IOCTL_MAGIC, HAILO_DISABLE_NOTIFICATION_CODE)
@@ -311,6 +341,8 @@ enum hailo_vdma_ioctl_code {
HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC_CODE,
HAILO_VDMA_LOW_MEMORY_BUFFER_FREE_CODE,
HAILO_MARK_AS_IN_USE_CODE,
HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC_CODE,
HAILO_VDMA_CONTINUOUS_BUFFER_FREE_CODE,
// Must be last
HAILO_VDMA_IOCTL_MAX_NR,
@@ -331,11 +363,15 @@ enum hailo_vdma_ioctl_code {
#define HAILO_DESC_LIST_RELEASE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_RELEASE_CODE)
#define HAILO_DESC_LIST_BIND_VDMA_BUFFER _IOR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_DESC_LIST_BIND_VDMA_BUFFER_CODE, struct hailo_desc_list_bind_vdma_buffer_params)
#define HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC_CODE, struct hailo_allocate_buffer_params)
#define HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_LOW_MEMORY_BUFFER_ALLOC_CODE, struct hailo_allocate_low_memory_buffer_params)
#define HAILO_VDMA_LOW_MEMORY_BUFFER_FREE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_LOW_MEMORY_BUFFER_FREE_CODE)
#define HAILO_MARK_AS_IN_USE _IOW_(HAILO_VDMA_IOCTL_MAGIC, HAILO_MARK_AS_IN_USE_CODE, struct hailo_mark_as_in_use_params)
#define HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC _IOWR_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CONTINUOUS_BUFFER_ALLOC_CODE, struct hailo_allocate_continuous_buffer_params)
#define HAILO_VDMA_CONTINUOUS_BUFFER_FREE _IO_(HAILO_VDMA_IOCTL_MAGIC, HAILO_VDMA_CONTINUOUS_BUFFER_FREE_CODE)
enum hailo_windows_ioctl_code {
HAILO_WINDOWS_DESC_LIST_MMAP_CODE,

View File

@@ -0,0 +1,124 @@
/*++
Module Name:
public.h
Abstract:
This module contains the common declarations shared by driver
and user applications.
Environment:
user and kernel
--*/
//
// Define an Interface Guid so that apps can find the device and talk to it.
//
DEFINE_GUID (GUID_DEVINTERFACE_HailoKM,
0xd88d31f1,0xfede,0x4e71,0xac,0x2a,0x6c,0xe0,0x01,0x8c,0x15,0x01);
// {d88d31f1-fede-4e71-ac2a-6ce0018c1501}
#define HAILO_IOCTL_COMMON CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_FUNC(x) (((x) >> 2) & 0xfff)
#define NUMBER_OF_PARAMETERS(code) ((code) & 0xf)
#define NUMBER_OF_PARAMETERS_FLEXIBLE 0xf
struct tCommonHailoIoctlParam
{
ULONG ulCode : 24;
ULONG fResponse : 1;
ULONG fUseLL : 1;
ULONG ulParamNum : 4;
union {
ULONG ulInputs[4];
ULONGLONG llInputs[2];
};
union {
ULONG ulOutputs[4];
ULONGLONG llOutputs[2];
};
};
#define HAILO_CMD_FW_LOAD 0x0010
#define HAILO_CMD_READ_CFG 0x0011
#define HAILO_CMD_SW_RESET 0x0020
#define HAILO_CMD_READ_INTERRUPT_BAR 0x0021
#define HAILO_CMD_READ_FW_STATUS 0x0030
#define HAILO_CMD_READ_FIRMWARE_BAR 0x0031
#define HAILO_CMD_CANCEL_READ 0x0040
#define HAILO_CMD_READ_RP_CFG 0x0041
#define HAILO_CMD_UNMAP_BUFFER 0x0050
#define HAILO_CMD_MAP_BUFFER 0x0051
#define HAILO_CMD_FREE_MEMORY 0x0060
#define HAILO_CMD_ALLOC_MEMORY 0x0061
#define HAILO_CMD_ABORT_ALL 0x0070
#define HAILO_IOCTL_COMPATIBLE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct tCompatibleHailoIoctlParam
{
union {
struct {
ULONG Size : 16;
ULONG Code : 8;
ULONG Type : 6;
ULONG Read : 1;
ULONG Write : 1;
} bits;
ULONG value;
} u;
};
#define HAILO_GENERAL_IOCTL_MAGIC 0
#define HAILO_VDMA_IOCTL_MAGIC 1
#define HAILO_WINDOWS_IOCTL_MAGIC 2
static ULONG FORCEINLINE _IOC_(ULONG nr, ULONG type, ULONG size, bool read, bool write)
{
tCompatibleHailoIoctlParam param;
param.u.bits.Code = nr;
param.u.bits.Size = size;
param.u.bits.Type = type;
param.u.bits.Read = read ? 1 : 0;
param.u.bits.Write = write ? 1 : 0;
return param.u.value;
}
#define _IOW_(type,nr,size) _IOC_(nr, type, sizeof(size), true, false)
#define _IOR_(type,nr,size) _IOC_(nr, type, sizeof(size), false, true)
#define _IOWR_(type,nr,size) _IOC_(nr, type, sizeof(size), true, true)
#define _IO_(type,nr) _IOC_(nr, type, 0, false, false)
#include "..\..\common\hailo_ioctl_common.h"
struct tCompatibleHailoIoctlData
{
tCompatibleHailoIoctlParam Parameters;
ULONG_PTR Value;
union {
hailo_bar_transfer_params BarTransfer;
hailo_vdma_channel_enable_params ChannelEnable;
hailo_vdma_channel_disable_params ChannelDisable;
hailo_vdma_channel_wait_params ChannelWait;
hailo_vdma_channel_abort_params ChannelAbort;
hailo_vdma_channel_clear_abort_params ChannelClearAbort;
hailo_vdma_buffer_sync_params VdmaBufferSync;
hailo_fw_control FirmwareControl;
hailo_vdma_buffer_map_params VdmaBufferMap;
hailo_desc_list_create_params DescListCreate;
hailo_desc_list_bind_vdma_buffer_params DescListBind;
hailo_d2h_notification D2HNotification;
hailo_device_properties DeviceProperties;
hailo_driver_info DriverInfo;
hailo_channel_registers_params ChannelRegisters;
hailo_windows_desc_list_mmap_params DescListMmap;
hailo_read_log_params ReadLog;
hailo_mark_as_in_use_params MarkAsInUse;
} Buffer;
};

View File

@@ -0,0 +1,10 @@
#ifndef _HAILO_PCIE_VERSION_H_
#define _HAILO_PCIE_VERSION_H_
#include "..\..\common\hailo_pcie_version.h"
#define STRINGIFY_EXPANDED( x ) #x
#define STRINGIFY_NUMBER( x ) STRINGIFY_EXPANDED(x)
#define HAILO_DRV_VER STRINGIFY_NUMBER(HAILO_DRV_VER_MAJOR) "." STRINGIFY_NUMBER(HAILO_DRV_VER_MINOR) "." STRINGIFY_NUMBER(HAILO_DRV_VER_REVISION)
#endif /* _HAILO_PCIE_VERSION_H_ */

View File

@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0.0)
include(GNUInstallDirs)
set(HAILORTCLI_CPP_FILES
hailortcli.cpp
command.cpp
@@ -29,7 +31,6 @@ if(UNIX)
udp_rate_limiter_command.cpp
# TODO: We dont compile download_action_list_command on windows, as it uses packed enums (HRT-5919)
download_action_list_command.cpp
)
endif()
@@ -50,11 +51,16 @@ add_executable(hailortcli
)
target_compile_options(hailortcli PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailortcli PROPERTY CXX_STANDARD 14)
set_property(TARGET hailortcli PROPERTY INSTALL_RPATH "$ORIGIN") # Need to add "${CMAKE_INSTALL_LIBDIR}" when installing with cmake to /usr/local
set_property(TARGET hailortcli PROPERTY INSTALL_RPATH "$ORIGIN" "../lib/") # Link with a relative libhailort
target_link_libraries(hailortcli libhailort CLI11::CLI11 nlohmann_json spdlog::spdlog readerwriterqueue)
target_link_libraries(hailortcli DotWriter)
# TODO: Remove microprofile after removing pipeline.cpp from hailortcli sources
target_link_libraries(hailortcli microprofile)
if(WIN32)
target_link_libraries(hailortcli Ws2_32 Iphlpapi Shlwapi)
elseif(CMAKE_SYSTEM_NAME STREQUAL QNX)
target_link_libraries(hailortcli pevents)
endif()
target_include_directories(hailortcli
PRIVATE

View File

@@ -28,13 +28,20 @@ BenchmarkCommand::BenchmarkCommand(CLI::App &parent_app) :
m_app->add_option("hef", m_params.hef_path, "Path of the HEF to load")
->check(CLI::ExistingFile)
->required();
m_app->add_option("-t, --time-to-run", m_time, "Measurement time in seconds per hw_only/streaming/latency measurement mode")
m_app->add_option("-t, --time-to-run", m_params.time_to_run, "Measurement time in seconds per hw_only/streaming/latency measurement mode")
->check(CLI::PositiveNumber)
->default_val(15);
m_app->add_option("--no-power", m_not_measure_power, "Skip power measurement, even if the platform supports it. The default value is False")
->default_val("false");
m_app->add_option("--batch-size", m_params.batch_size, "Inference batch size (default is 1)")
->default_val(1);
m_app->add_option("--power-mode", m_params.power_mode,
"Core power mode (PCIE only; ignored otherwise)")
->transform(HailoCheckedTransformer<hailo_power_mode_t>({
{ "performance", hailo_power_mode_t::HAILO_POWER_MODE_PERFORMANCE },
{ "ultra_performance", hailo_power_mode_t::HAILO_POWER_MODE_ULTRA_PERFORMANCE }
}))
->default_val("performance");
m_app->add_option("--input-files", m_params.inputs_name_and_file_path, " The input files need to be in UINT8 before transformations.")
->check(InputNameToFileMap);
m_app->add_option("--csv", m_csv_file_path, "If set print the output as csv to the specified path");
@@ -66,6 +73,7 @@ hailo_status BenchmarkCommand::execute()
auto streaming_mode_info = fps_streaming_mode();
CHECK_EXPECTED_AS_STATUS(streaming_mode_info, "FPS in streaming mode failed");
// TODO - HRT-6931 - measure latnecy only in the case of single device.
std::cout << "Measuring HW Latency" << std::endl;
auto latency_info = latency();
CHECK_EXPECTED_AS_STATUS(latency_info, "Latency measuring failed");
@@ -110,7 +118,6 @@ Expected<NetworkGroupInferResult> BenchmarkCommand::hw_only_mode()
m_params.power_measurement.measure_power = false;
m_params.measure_latency = false;
m_params.mode = InferMode::HW_ONLY;
m_params.time_to_run = m_time;
return run_command_hef(m_params);
}
@@ -121,7 +128,6 @@ Expected<NetworkGroupInferResult> BenchmarkCommand::fps_streaming_mode()
m_params.measure_latency = false;
m_params.transform.transform = true;
m_params.transform.quantized = false;
m_params.time_to_run = m_time;
return run_command_hef(m_params);
}
@@ -132,6 +138,5 @@ Expected<NetworkGroupInferResult> BenchmarkCommand::latency()
m_params.mode = InferMode::STREAMING;
m_params.transform.transform = true;
m_params.transform.quantized = false;
m_params.time_to_run = m_time;
return run_command_hef(m_params);
}

View File

@@ -27,7 +27,6 @@ private:
inference_runner_params m_params;
bool m_not_measure_power;
uint32_t m_time;
std::string m_csv_file_path;
};

View File

@@ -41,6 +41,10 @@ DeviceCommand::DeviceCommand(CLI::App *app) :
hailo_status DeviceCommand::execute()
{
if ((DeviceType::PCIE == m_device_params.device_type ) &&
("*" == m_device_params.pcie_params.pcie_bdf)) {
return execute_on_all_pcie_devices();
}
auto device = create_device(m_device_params);
if (!device) {
return device.status();
@@ -49,23 +53,24 @@ hailo_status DeviceCommand::execute()
return execute_on_device(*device.value());
}
PcieDeviceCommand::PcieDeviceCommand(CLI::App *app) :
Command(app)
hailo_status DeviceCommand::execute_on_all_pcie_devices()
{
auto group = app->add_option_group("PCIE Device Options");
// PCIe options
group->add_option("-s,--bdf", m_pcie_device_params.pcie_bdf,
"Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command)")
->default_val("");
auto status = HAILO_SUCCESS; // Best effort
auto all_devices_infos = Device::scan_pcie();
if (!all_devices_infos) {
return all_devices_infos.status();
}
hailo_status PcieDeviceCommand::execute()
{
auto device = create_pcie_device(m_pcie_device_params);
for (auto &dev_info : all_devices_infos.value()) {
auto device = Device::create_pcie(dev_info);
if (!device) {
return device.status();
}
return execute_on_device(*device.value());
auto execute_status = execute_on_device(*device.value());
if (HAILO_SUCCESS != execute_status) {
std::cerr << "Failed to execute on device: " << device.value()->get_dev_id() << ". status= " << execute_status << std::endl;
status = execute_status;
}
}
return status;
}

View File

@@ -26,11 +26,6 @@ public:
return m_app->parsed();
}
void set_description(const std::string &new_desc)
{
m_app->description(new_desc);
}
void set_footer(const std::string &new_footer)
{
m_app->footer(new_footer);
@@ -70,21 +65,10 @@ public:
protected:
virtual hailo_status execute_on_device(Device &device) = 0;
hailo_status execute_on_all_pcie_devices();
private:
hailo_device_params m_device_params;
};
class PcieDeviceCommand : public Command {
public:
explicit PcieDeviceCommand(CLI::App *app);
virtual hailo_status execute() override final;
protected:
virtual hailo_status execute_on_device(Device &device) = 0;
private:
hailo_pcie_params m_pcie_device_params;
};
#endif /* _HAILO_COMMAND_HPP_ */

View File

@@ -13,6 +13,7 @@
#include "md5.h"
#include <iostream>
#include <iomanip>
constexpr int DownloadActionListCommand::INVALID_NUMERIC_VALUE;
@@ -21,7 +22,7 @@ DownloadActionListCommand::DownloadActionListCommand(CLI::App &parent_app) :
{
static const char *JSON_SUFFIX = ".json";
m_app->add_option("--output-file", m_output_file_path, "Output file path")
->default_val("context_action_list.json")
->default_val("runtime_data.json")
->check(FileSuffixValidator(JSON_SUFFIX));
}
@@ -59,6 +60,11 @@ hailo_status DownloadActionListCommand::execute(Device &device, const std::strin
return HAILO_SUCCESS;
}
hailo_status DownloadActionListCommand::set_batch_to_measure(Device &device, uint16_t batch_to_measure)
{
return device.set_context_action_list_timestamp_batch(batch_to_measure);
}
hailo_status DownloadActionListCommand::execute_on_device(Device &device)
{
return execute(device, m_output_file_path);
@@ -101,7 +107,8 @@ Expected<std::string> DownloadActionListCommand::calc_md5_hexdigest(const std::s
std::stringstream hexdigest;
for (uint32_t i = 0; i < ARRAY_ENTRIES(md5_sum); i++) {
// cast to int needed for proper formatting
hexdigest << std::hex << static_cast<int>(md5_sum[i]);
static const int NUM_HEX_DIGITS_IN_UNIT8 = 2;
hexdigest << std::hex << std::setfill('0') << std::setw(NUM_HEX_DIGITS_IN_UNIT8) << static_cast<int>(md5_sum[i]);
}
return hexdigest.str();
@@ -180,9 +187,9 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__application_change_interrupt_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__read_vdma_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__read_vdma_action_data_t);
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CCW_BURSTS:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t *>(action);
@@ -200,6 +207,10 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t);
@@ -248,6 +259,10 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = json({});
action_length_local = 0;
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START:
data_json = json({});
action_length_local = 0;
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_CFG_CHANNEL:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__activate_cfg_channel_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__activate_cfg_channel_t);
@@ -391,7 +406,7 @@ Expected<ordered_json> DownloadActionListCommand::parse_network_groups(Device &d
return network_group_list_json;
}
void to_json(json& j, const CONTEXT_SWITCH_DEFS__read_vdma_action_data_t& data) {
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data) {
j = json{{"descriptors_count", data.descriptors_count}, {"channel_index", data.cfg_channel_number}};
}

View File

@@ -27,6 +27,7 @@ public:
// To be used from external commands
static hailo_status execute(Device &device, const std::string &output_file_path,
const ConfiguredNetworkGroupVector &network_groups={}, const std::string &hef_file_path="");
static hailo_status set_batch_to_measure(Device &device, uint16_t batch_to_measure);
protected:
virtual hailo_status execute_on_device(Device &device) override;
@@ -62,7 +63,7 @@ private:
// JSON serialization
NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_VDMA_DESCRIPTORS, "fetch_vdma_descriptors"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_CFG_CHANNEL_DESCRIPTORS, "fetch_cfg_channel_descriptors"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_TRIGGER_SEQUENCER, "trigger_sequencer"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_FETCH_DATA_FROM_VDMA_CHANNEL, "fetch_data_from_vdma_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ENABLE_LCU_DEFAULT, "enable_lcu_default"},
@@ -75,9 +76,11 @@ NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_DDR_BUFFER_INPUT, "activate_ddr_buffer_input"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_DDR_BUFFER_OUTPUT, "activate_ddr_buffer_output"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DEACTIVATE_VDMA_CHANNEL, "deactivate_vdma_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_VALIDATE_VDMA_CHANNEL, "validate_vdma_channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_CHANGE_VDMA_TO_STREAM_MAPPING, "change_vdma_to_stream_mapping"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_ADD_DDR_PAIR_INFO, "add_ddr_pair_info"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_DDR_BUFFERING_START, "ddr_buffering_start"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_BURST_CREDITS_TASK_START, "burst_credits_task_start"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_LCU_INTERRUPT, "lcu_interrupt"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_SEQUENCER_DONE_INTERRUPT, "sequencer_done_interrupt"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_INPUT_CHANNEL_TRANSFER_DONE_INTERRUPT, "input_channel_transfer_done_interrupt"},
@@ -97,6 +100,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, {
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__repeated_action_header_t, count, last_executed, sub_action_type);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__trigger_sequencer_action_data_t, cluster_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t, vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__validate_vdma_channel_action_data_t, vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__fetch_data_action_data_t, vdma_channel_index, stream_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__add_ddr_pair_info_action_data_t, h2d_vdma_channel_index, d2h_vdma_channel_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__vdma_dataflow_interrupt_data_t, vdma_channel_index);
@@ -118,7 +122,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__deactivate_cfg_channel_t
void to_json(json& j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_default_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__enable_lcu_action_non_default_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__disable_lcu_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__read_vdma_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_cfg_channel_descriptors_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__change_vdma_to_stream_mapping_data_t& data);
void to_json(json& j, const CONTEXT_SWITCH_DEFS__lcu_interrupt_data_t& data);

View File

@@ -230,19 +230,9 @@ FwControlCommand::FwControlCommand(CLI::App &parent_app) :
{
add_subcommand<FwControlIdentifyCommand>();
add_subcommand<FwControlResetCommand>();
// TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)
// Can also remove Command::set_description function after this, and the return value of `add_subcommand`
auto &scan = add_subcommand<ScanSubcommand>();
scan.set_description("Alias for root-level 'scan' command (i.e. 'hailortcli scan...')\n"
"Note: 'scan' as a sub-command of 'fw-control' is deprecated; use 'hailortcli scan' instead\n"
" (or 'hailo scan' when using the 'hailo' command).");
add_subcommand<FwControlTestMemoriesCommand>();
// TODO: Support on windows (HRT-5919)
#if defined(__GNUC__)
// TODO: Unhide (HRT-6035)
static const bool HIDDEN = true;
add_subcommand<DownloadActionListCommand>(HIDDEN);
add_subcommand<DownloadActionListCommand>();
#endif
}

View File

@@ -12,8 +12,6 @@
#include "hailortcli.hpp"
#include "command.hpp"
// TODO: Remove scan as a subcommand of fw_control_subcommand (HRT-2676)
#include "scan_command.hpp"
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
#include "download_action_list_command.hpp"

View File

@@ -120,25 +120,19 @@ void add_device_options(CLI::App *app, hailo_device_params &device_params)
auto group = app->add_option_group("Device Options");
// TODO: `--target` and `udp` DeviceType::ETH are for backwards compatibility with the python implemention (`hailo`)
// TODO: Remove them (HRT-2676)
const HailoCheckedTransformer<DeviceType> device_type_transformer({
{ "pcie", DeviceType::PCIE },
{ "eth", DeviceType::ETH },
{ "udp", DeviceType::ETH },
});
auto *device_type_option = group->add_option("-d,--device-type,--target", device_params.device_type,
"Device type to use\n"
"Default is pcie.\n"
"Note: 'udp' is an alias for 'eth'.")
"Default is pcie.")
->transform(device_type_transformer);
std::vector<DeprecationActionPtr> actions{ std::make_shared<ValueDeprecation>(device_type_option, "udp", "eth") };
hailo_deprecate_options(app, actions, false);
// PCIe options
auto *pcie_bdf_option = group->add_option("-s,--bdf", device_params.pcie_params.pcie_bdf,
"Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command)")
"Device id ([<domain>]:<bus>:<device>.<func>, same as in lspci command).\n" \
"In order to run on all PCIe devices connected to the machine one-by-one, use '*' (instead of device id).")
->default_val("");
// Ethernet options
@@ -194,6 +188,28 @@ void add_vdevice_options(CLI::App *app, hailo_device_params &device_params) {
});
}
static bool do_versions_match()
{
hailo_version_t libhailort_version = {};
auto status = hailo_get_library_version(&libhailort_version);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to get libhailort version" << std::endl;
return false;
}
bool versions_match = ((HAILORT_MAJOR_VERSION == libhailort_version.major) &&
(HAILORT_MINOR_VERSION == libhailort_version.minor) &&
(HAILORT_REVISION_VERSION == libhailort_version.revision));
if (!versions_match) {
std::cerr << "libhailort version (" <<
libhailort_version.major << "." << libhailort_version.minor << "." << libhailort_version.revision <<
") does not match HailoRT-CLI version (" <<
HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << ")" << std::endl;
return false;
}
return true;
}
class HailoRTCLI : public ContainerCommand {
public:
HailoRTCLI(CLI::App *app) : ContainerCommand(app)
@@ -201,7 +217,7 @@ public:
m_app->add_flag_callback("-v,--version",
[] () {
std::cout << "hailortcli version " <<
std::cout << "HailoRT-CLI version " <<
HAILORT_MAJOR_VERSION << "." << HAILORT_MINOR_VERSION << "." << HAILORT_REVISION_VERSION << std::endl;
// throw CLI::Success to stop parsing and not failing require_subcommand(1) we set earlier
throw (CLI::Success{});
@@ -235,6 +251,9 @@ public:
};
int main(int argc, char** argv) {
if (!do_versions_match()) {
return -1;
}
auto console_sink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
console_sink->set_level(spdlog::level::info);
console_sink->set_pattern("[%n] [%^%l%$] %v");

View File

@@ -28,7 +28,7 @@ using namespace hailort;
} while (0)
struct hailo_pcie_params {
std::string pcie_bdf; // if empty use the first scanned
std::string pcie_bdf; // if empty use the first scanned. if '*', run on all devices on the machine one-by-one
};
struct hailo_eth_params {

View File

@@ -10,9 +10,6 @@
#include "power_measurement_command.hpp"
#include <thread>
#define POWER_MEASUREMENT_DELAY_MS(__sample_period, __average_factor) \
(static_cast<uint32_t>((__sample_period) / 1000.0 * (__average_factor) * 2 * 1.2))
PowerMeasurementSubcommand::PowerMeasurementSubcommand(CLI::App &parent_app) :
DeviceCommand(parent_app.add_subcommand("measure-power", "Measures power consumption")), m_params(),
@@ -120,19 +117,13 @@ Expected<LongPowerMeasurement> PowerMeasurementSubcommand::start_power_measureme
return make_unexpected(status);
}
status = hailo_set_power_measurement(reinterpret_cast<hailo_device>(&device), 0, dvm, measurement_type);
status = hailo_set_power_measurement(reinterpret_cast<hailo_device>(&device), HAILO_MEASUREMENT_BUFFER_INDEX_0, dvm, measurement_type);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to set power measurement parameters, status " << status << std::endl;
return make_unexpected(status);
}
uint32_t measurement_delay = POWER_MEASUREMENT_DELAY_MS(sampling_period, averaging_factor);
// There is no logical way that measurement delay can be 0 - because sampling_period and averaging_factor cant be 0
// Hence if it is 0 - it means it was 0.xx and we want to round up to 1 in that case
if (0 == measurement_delay) {
measurement_delay = 1;
}
status = hailo_start_power_measurement(reinterpret_cast<hailo_device>(&device), measurement_delay,
status = hailo_start_power_measurement(reinterpret_cast<hailo_device>(&device),
averaging_factor_enum, sampling_period_enum);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to start power measurement, status " << status << std::endl;
@@ -155,7 +146,7 @@ hailo_status LongPowerMeasurement::stop()
return status;
}
status = hailo_get_power_measurement(reinterpret_cast<hailo_device>(&m_device), 0, true, &m_data);
status = hailo_get_power_measurement(reinterpret_cast<hailo_device>(&m_device), HAILO_MEASUREMENT_BUFFER_INDEX_0, true, &m_data);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to get power measurement results, status " << status << std::endl;
return status;

View File

@@ -61,7 +61,7 @@ void user_signal_handler_func(int signum)
hailo_status wait_for_exit_with_timeout(std::chrono::seconds time_to_run)
{
#if defined(__unix__)
#if defined(__linux__)
sighandler_t prev_handler = signal(USER_SIGNAL, user_signal_handler_func);
CHECK(prev_handler != SIG_ERR, HAILO_INVALID_OPERATION, "signal failed, errno = {}", errno);
std::mutex mutex;
@@ -100,8 +100,6 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
auto hef_new = run_subcommand->add_option("hef", params.hef_path, "An existing HEF file/directory path")
->check(CLI::ExistingFile | CLI::ExistingDirectory);
auto hef_old = run_subcommand->add_option("--hef", params.hef_path, "An existing HEF file/directory path")
->check(CLI::ExistingFile | CLI::ExistingDirectory);
// Allow multiple subcommands (see https://cliutils.github.io/CLI11/book/chapters/subcommands.html)
run_subcommand->require_subcommand(0, 0);
@@ -202,20 +200,20 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
// TODO: Support on windows (HRT-5919)
#if defined(__GNUC__)
// TODO: Unhide (HRT-6035)
// Unnamed "option groups" hide subcommands/options from the help message
// (see https://github.com/CLIUtils/CLI11/blob/main/README.md)
auto *hidden_group = run_subcommand->add_option_group("");
auto *download_runtime_data_subcommand = hidden_group->add_subcommand("download-runtime-data",
"Download runtime data to be used by the Profiler");
auto *collect_runtime_data_subcommand = run_subcommand->add_subcommand("collect-runtime-data",
"Collect runtime data to be used by the Profiler");
static const char *JSON_SUFFIX = ".json";
download_runtime_data_subcommand->add_option("--output-path",
collect_runtime_data_subcommand->add_option("--output-path",
params.runtime_data.runtime_data_output_path, "Runtime data output file path")
->default_val("context_action_list.json")
->default_val("runtime_data.json")
->check(FileSuffixValidator(JSON_SUFFIX));
download_runtime_data_subcommand->parse_complete_callback([&params]() {
static const uint32_t DEFAULT_BATCH_TO_MEASURE = 2;
collect_runtime_data_subcommand->add_option("--batch-to-measure",
params.runtime_data.batch_to_measure, "Batch to be measured")
->default_val(DEFAULT_BATCH_TO_MEASURE);
collect_runtime_data_subcommand->parse_complete_callback([&params]() {
// If this subcommand was parsed, then we need to download runtime_data
params.runtime_data.download_runtime_data = true;
params.runtime_data.collect_runtime_data = true;
});
#endif
@@ -229,9 +227,9 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
run_subcommand->add_flag("--measure-temp", params.measure_temp, "Measure chip temperature");
run_subcommand->parse_complete_callback([&params, hef_new, hef_old, power_sampling_period,
run_subcommand->parse_complete_callback([&params, hef_new, power_sampling_period,
power_averaging_factor, measure_power_opt, measure_current_opt]() {
PARSE_CHECK(hef_new->empty() ^ hef_old->empty(), "Single HEF file/directory is required");
PARSE_CHECK(!hef_new->empty(), "Single HEF file/directory is required");
bool is_hw_only = InferMode::HW_ONLY == params.mode;
params.transform.transform = (!is_hw_only || (params.inputs_name_and_file_path.size() > 0));
PARSE_CHECK((!params.transform.quantized || (HAILO_FORMAT_TYPE_AUTO == params.transform.format_type)),
@@ -248,16 +246,22 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
!(params.power_measurement.measure_power || params.power_measurement.measure_current || params.measure_temp),
"Writing measurements in csv format is not supported for multiple devices");
PARSE_CHECK(("*" != params.device_params.pcie_params.pcie_bdf),
"Passing '*' as BDF is not supported for 'run' command. for multiple devices inference see '--device-count'");
if ((0 == params.time_to_run) && (0 == params.frames_count)) {
// Use default
params.time_to_run = DEFAULT_TIME_TO_RUN_SECONDS;
}
});
std::vector<DeprecationActionPtr> actions{
std::make_shared<OptionDeprecation>(hef_old, "hef (positional)"),
};
hailo_deprecate_options(run_subcommand, actions, false);
if (params.runtime_data.collect_runtime_data) {
if ((0 != params.frames_count) && (params.frames_count < params.runtime_data.batch_to_measure)) {
LOGGER__WARNING("--frames-count ({}) is smaller than --batch-to-measure ({}), "
"hence timestamps will not be updated in runtime data", params.frames_count,
params.runtime_data.batch_to_measure);
}
}
});
}
std::map<std::string, std::string> format_strings_to_key_value_pairs(const std::vector<std::string> &key_value_pairs_str) {
@@ -1030,18 +1034,34 @@ Expected<NetworkGroupInferResult> run_command_hef_single_device(const inference_
auto network_group_list = device.value()->configure(hef.value(), configure_params.value());
CHECK_EXPECTED(network_group_list, "Failed configure device from hef");
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
if (params.runtime_data.collect_runtime_data) {
DownloadActionListCommand::set_batch_to_measure(*device.value(), params.runtime_data.batch_to_measure);
}
#endif
// TODO: SDK-14842, for now this function supports only one network_group
auto network_group = network_group_list.value()[0];
auto inference_result = activate_network_group_and_run(*device.value().get(), network_group, params);
#if defined(__GNUC__)
// TODO: Support on windows (HRT-5919)
if (params.runtime_data.download_runtime_data) {
if (params.runtime_data.collect_runtime_data) {
if ((0 == params.frames_count) && inference_result) {
const auto frames_count = inference_result->frames_count();
if (frames_count && (frames_count.value() < params.runtime_data.batch_to_measure)) {
LOGGER__WARNING("Number of frames sent ({}) is smaller than --batch-to-measure ({}), "
"hence timestamps will not be updated in runtime data", frames_count.value(),
params.runtime_data.batch_to_measure);
}
}
DownloadActionListCommand::execute(*device.value(), params.runtime_data.runtime_data_output_path,
network_group_list.value(), params.hef_path);
}
#endif
CHECK_EXPECTED(inference_result);
return inference_result;
}

View File

@@ -45,8 +45,9 @@ struct pipeline_stats_measurement_params {
};
struct runtime_data_params {
bool download_runtime_data;
bool collect_runtime_data;
std::string runtime_data_output_path;
uint16_t batch_to_measure;
};
struct inference_runner_params {

View File

@@ -17,39 +17,28 @@ ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
Command(parent_app.add_subcommand("scan", "Shows all available devices")),
m_device_type(Device::Type::PCIE)
{
// TODO: `--target` and `udp` Device::TYPE::ETH are for backwards compatibility with the python implemention (`hailo`)
// TODO: Remove them (HRT-2676)
const HailoCheckedTransformer<Device::Type> device_type_transformer({
{ "pcie", Device::Type::PCIE },
{ "eth", Device::Type::ETH },
{ "udp", Device::Type::ETH },
});
auto *device_type_option = m_app->add_option("-d,--device-type,--target", m_device_type,
"Device type to use\n"
"Note: 'udp' is an alias for 'eth'.")
"Device type to use.")
->transform(device_type_transformer)
->default_val("pcie");
// Ethernet options
auto *eth_options_group = m_app->add_option_group("Ethernet Device Options");
// TODO: `--ip` is for backwards compatibility with the python implemention (`hailo`)
// TODO: Remove it (HRT-2676)
auto *interface_ip_option = eth_options_group->add_option("--interface-ip", m_interface_ip_addr,
"Interface IP address to scan")
->default_val("")
->check(CLI::ValidIPV4);
auto *ip_option = eth_options_group->add_option("--ip", m_interface_ip_addr)
->default_val("")
->excludes(interface_ip_option)
->check(CLI::ValidIPV4);
auto *interface_name_option = eth_options_group->add_option("--interface", m_interface_name, "Interface name to scan")
->default_val("")
->excludes(interface_ip_option)
->excludes(ip_option);
->excludes(interface_ip_option);
m_app->parse_complete_callback([this, device_type_option, interface_ip_option, ip_option, interface_name_option]() {
bool eth_options_given = !interface_ip_option->empty() || !ip_option->empty() || !interface_name_option->empty();
m_app->parse_complete_callback([this, device_type_option, interface_ip_option, interface_name_option]() {
bool eth_options_given = !interface_ip_option->empty() || !interface_name_option->empty();
// The user didn't put target, we can figure it ourself
if (device_type_option->empty()) {
@@ -71,12 +60,6 @@ ScanSubcommand::ScanSubcommand(CLI::App &parent_app) :
throw CLI::ParseError("Ethernet options set on non eth device", CLI::ExitCodes::InvalidError);
}
});
std::vector<DeprecationActionPtr> actions{
std::make_shared<ValueDeprecation>(device_type_option, "udp", "eth"),
std::make_shared<OptionDeprecation>(ip_option, "--interface-ip")
};
hailo_deprecate_options(m_app, actions, false);
}
hailo_status ScanSubcommand::execute()

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
set(HAILORT_MINOR_VERSION 6)
set(HAILORT_MINOR_VERSION 8)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found

View File

@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.0.0)
if(HAILO_BUILD_PYBIND)
add_subdirectory(python)
endif()
# QNX currently doesnt support GStreamer
if(HAILO_BUILD_GSTREAMER AND CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL QNX)
add_subdirectory(gstreamer)

View File

@@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.0.0)
project(gsthailo)
include(GNUInstallDirs)
if(NOT CMAKE_HOST_UNIX)
message(FATAL_ERROR "Only unix hosts are supported, stopping build")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/")
find_package(HailoRT)
find_package(HailoRT 4.8.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")

View File

@@ -1,28 +0,0 @@
# - Try to find HailoRT
# - If libhailort is defined (building as part of the build tree), use it
# - Otherwise, find HAILORT_LIB and HAILORT_INCLUDE_DIR, and import libhailort
if (NOT TARGET libhailort)
# find_path finds a directory containing the named file
find_path(HAILORT_INCLUDE_DIR "hailo/" PATH_SUFFIXES "include/")
find_library(HAILORT_LIB "libhailort.so.4.6.0" PATH_SUFFIXES "lib/")
include(FindPackageHandleStandardArgs)
# Handle the QUIETLY and REQUIRED arguments and set HAILORT_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(
HailoRT
DEFAULT_MSG
HAILORT_LIB
HAILORT_INCLUDE_DIR
)
add_library(HailoRT::libhailort SHARED IMPORTED)
set_target_properties(HailoRT::libhailort PROPERTIES
IMPORTED_LOCATION "${HAILORT_LIB}"
INTERFACE_INCLUDE_DIRECTORIES "${HAILORT_INCLUDE_DIR}"
)
else()
add_library(HailoRT::libhailort ALIAS libhailort)
endif()

View File

@@ -51,6 +51,9 @@ using namespace hailort;
#define HAILO_SUPPORTED_FORMATS "{ RGB, YUY2 }"
#define HAILO_VIDEO_CAPS GST_VIDEO_CAPS_MAKE(HAILO_SUPPORTED_FORMATS)
#define HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS (0)
#define HAILO_DEFAULT_SCHEDULER_THRESHOLD (1)
#define GST_CHECK(cond, ret_val, element, domain, ...) \
do { \
if (!(cond)) { \

View File

@@ -31,7 +31,6 @@ GST_DEBUG_CATEGORY_STATIC(gst_hailodevicestats_debug_category);
2 * sampling_period (1.1) * averaging_factor (256) [ms].
Therefore we want it to be the period of time that the core will sleep between samples,
plus a factor of 20 percent */
#define POWER_MEASUREMENT_DELAY_MS (static_cast<uint32_t>(1100 / 1000.0 * 256 * 2 * 1.2))
static void gst_hailodevicestats_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
static void gst_hailodevicestats_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
@@ -226,10 +225,10 @@ hailo_status HailoDeviceStatsImpl::run_measure_loop()
hailo_status status = m_device->stop_power_measurement();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Stopping power measurement failed, status = %d", status);
status = m_device->set_power_measurement(0, HAILO_DVM_OPTIONS_AUTO, HAILO_POWER_MEASUREMENT_TYPES__AUTO);
status = m_device->set_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, HAILO_DVM_OPTIONS_AUTO, HAILO_POWER_MEASUREMENT_TYPES__AUTO);
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting power measurement parameters failed, status = %d", status);
status = m_device->start_power_measurement(POWER_MEASUREMENT_DELAY_MS, HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
status = m_device->start_power_measurement(HAILO_DEFAULT_INIT_AVERAGING_FACTOR, HAILO_DEFAULT_INIT_SAMPLING_PERIOD_US);
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Starting power measurement failed, status = %d", status);
auto device_string = Device::pcie_device_info_to_string(m_device_info);
@@ -237,7 +236,7 @@ hailo_status HailoDeviceStatsImpl::run_measure_loop()
const char *device_raw_string = device_string->c_str();
while (m_is_thread_running.load()) {
auto measurement = m_device->get_power_measurement(0, true);
auto measurement = m_device->get_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, true);
GST_CHECK_EXPECTED_AS_STATUS(measurement, m_element, RESOURCE, "Getting power measurement failed, status = %d", measurement.status());
if (!m_is_silent) {

View File

@@ -30,6 +30,28 @@
GST_DEBUG_CATEGORY_STATIC(gst_hailonet_debug_category);
#define GST_CAT_DEFAULT gst_hailonet_debug_category
#define GST_TYPE_SCHEDULING_ALGORITHM (gst_scheduling_algorithm_get_type ())
static GType
gst_scheduling_algorithm_get_type (void)
{
static GType scheduling_algorithm_type = 0;
/* Tightly coupled to hailo_scheduling_algorithm_e */
if (!scheduling_algorithm_type) {
static GEnumValue algorithm_types[] = {
{ HAILO_SCHEDULING_ALGORITHM_NONE, "Scheduler is not active", "HAILO_SCHEDULING_ALGORITHM_NONE" },
{ HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN, "Round robin", "HAILO_SCHEDULING_ALGORITHM_ROUND_ROBIN" },
{ HAILO_SCHEDULING_ALGORITHM_MAX_ENUM, NULL, NULL },
};
scheduling_algorithm_type =
g_enum_register_static ("GstHailoSchedulingAlgorithms", algorithm_types);
}
return scheduling_algorithm_type;
}
constexpr std::chrono::milliseconds WAIT_FOR_FLUSH_TIMEOUT_MS(1000);
static void gst_hailonet_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
@@ -53,7 +75,10 @@ enum
PROP_OUTPUTS_MAX_POOL_SIZE,
PROP_IS_ACTIVE,
PROP_DEVICE_COUNT,
PROP_VDEVICE_KEY
PROP_VDEVICE_KEY,
PROP_SCHEDULING_ALGORITHM,
PROP_SCHEDULER_TIMEOUT_MS,
PROP_SCHEDULER_THRESHOLD,
};
G_DEFINE_TYPE(GstHailoNet, gst_hailonet, GST_TYPE_BIN);
@@ -116,9 +141,26 @@ static void gst_hailonet_class_init(GstHailoNetClass *klass)
DEFAULT_OUTPUTS_MAX_POOL_SIZE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_IS_ACTIVE,
g_param_spec_boolean("is-active", "Is Network Activated", "Controls whether this element should be active. "
"By default, the hailonet element will not be active unless there is only one hailonet in the pipeline", false,
"By default, the hailonet element will not be active unless it is the only one. "
"Setting this property in combination with 'scheduling-algorithm' different than HAILO_SCHEDULING_ALGORITHM_NONE is not supported.", false,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_SCHEDULING_ALGORITHM,
g_param_spec_enum("scheduling-algorithm", "Scheduling policy for automatic network group switching", "Controls the Model Scheduler algorithm of HailoRT. "
"Gets values from the enum GstHailoSchedulingAlgorithms. "
"Using Model Scheduler algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE, excludes the property 'is-active'. "
"When using the same VDevice across multiple hailonets, all should have the same 'scheduling-algorithm'. "
"Currently only supported with 1 device (e.g. device-count=1).",
GST_TYPE_SCHEDULING_ALGORITHM, HAILO_SCHEDULING_ALGORITHM_NONE,
(GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_SCHEDULER_TIMEOUT_MS,
g_param_spec_uint("scheduler-timeout-ms", "Timeout for for scheduler in ms", "The maximum time period that may pass before getting run time from the scheduler,"
" as long as at least one send request has been sent.",
HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS, std::numeric_limits<uint32_t>::max(), HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property(gobject_class, PROP_SCHEDULER_THRESHOLD,
g_param_spec_uint("scheduler-threshold", "Frames threshold for scheduler", "The minimum number of send requests required before the hailonet is considered ready to get run time from the scheduler.",
HAILO_DEFAULT_SCHEDULER_THRESHOLD, std::numeric_limits<uint32_t>::max(), HAILO_DEFAULT_SCHEDULER_THRESHOLD, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
// See information about the "flush" signal in the element description
g_signal_new(
"flush",
@@ -333,6 +375,11 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
{
gboolean new_is_active = g_value_get_boolean(value);
if (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get()) {
g_error("scheduling-algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE in combination with 'is-active' is not supported.");
break;
}
if (m_has_called_activate) {
if (m_props.m_is_active.get() && !new_is_active) {
// Setting this to false before deactivating to signal hailosend and hailorecv to stop inferring
@@ -358,6 +405,39 @@ void HailoNetImpl::set_property(GObject *object, guint property_id, const GValue
}
break;
}
case PROP_SCHEDULING_ALGORITHM:
if (m_was_configured) {
g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
break;
}
if (m_props.m_is_active.was_changed() && (g_value_get_enum(value) != HAILO_SCHEDULING_ALGORITHM_NONE)) {
g_error("scheduling-algorithm different than HAILO_SCHEDULING_ALGORITHM_NONE in combination with 'is-active' is not supported.");
break;
}
m_props.m_scheduling_algorithm = static_cast<hailo_scheduling_algorithm_t>(g_value_get_enum(value));
break;
case PROP_SCHEDULER_TIMEOUT_MS:
if (m_was_configured) {
g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
break;
}
if (m_props.m_is_active.was_changed()) {
g_error("scheduler usage (scheduler-timeout-ms) in combination with 'is-active' is not supported.");
break;
}
m_props.m_scheduler_timeout_ms = g_value_get_uint(value);
break;
case PROP_SCHEDULER_THRESHOLD:
if (m_was_configured) {
g_warning("The network was already configured so changing the scheduling algorithm will not take place!");
break;
}
if (m_props.m_is_active.was_changed()) {
g_error("scheduler usage (scheduler-threshold) in combination with 'is-active' is not supported.");
break;
}
m_props.m_scheduler_threshold = g_value_get_uint(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -416,6 +496,15 @@ void HailoNetImpl::get_property(GObject *object, guint property_id, GValue *valu
case PROP_IS_ACTIVE:
g_value_set_boolean(value, m_props.m_is_active.get());
break;
case PROP_SCHEDULING_ALGORITHM:
g_value_set_enum(value, m_props.m_scheduling_algorithm.get());
break;
case PROP_SCHEDULER_TIMEOUT_MS:
g_value_set_uint(value, m_props.m_scheduler_timeout_ms.get());
break;
case PROP_SCHEDULER_THRESHOLD:
g_value_set_uint(value, m_props.m_scheduler_threshold.get());
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -428,7 +517,7 @@ hailo_status HailoNetImpl::set_hef()
GST_CHECK(nullptr != m_net_group_handle, HAILO_OUT_OF_HOST_MEMORY, m_element, RESOURCE, "Failed allocating memory for network handle!");
hailo_status status = m_net_group_handle->set_hef(m_props.m_device_id.get(), m_props.m_device_count.get(), m_props.m_vdevice_key.get(),
m_props.m_hef_path.get());
m_props.m_scheduling_algorithm.get(), m_props.m_hef_path.get());
if (HAILO_SUCCESS != status) {
return status;
}
@@ -487,6 +576,15 @@ hailo_status HailoNetImpl::configure_network_group()
}
m_was_configured = true;
if (m_props.m_scheduler_timeout_ms.was_changed()) {
status = m_net_group_handle->set_scheduler_timeout(m_props.m_network_name.get(), m_props.m_scheduler_timeout_ms.get());
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting scheduler timeout failed, status = %d", status);
}
if (m_props.m_scheduler_threshold.was_changed()) {
status = m_net_group_handle->set_scheduler_threshold(m_props.m_network_name.get(), m_props.m_scheduler_threshold.get());
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Setting scheduler threshold failed, status = %d", status);
}
auto vstreams = m_net_group_handle->create_vstreams(m_props.m_network_name.get(), m_output_formats);
GST_CHECK_EXPECTED_AS_STATUS(vstreams, m_element, RESOURCE, "Creating vstreams failed, status = %d", status);
@@ -498,8 +596,13 @@ hailo_status HailoNetImpl::configure_network_group()
return HAILO_SUCCESS;
}
hailo_status HailoNetImpl::activate_network_group()
hailo_status HailoNetImpl::activate_hailonet()
{
if (HAILO_SCHEDULING_ALGORITHM_NONE != m_props.m_scheduling_algorithm.get()) {
m_props.m_is_active = true;
return HAILO_SUCCESS;
}
if ((1 == m_hailonet_count) && (!m_props.m_is_active.was_changed())) {
m_props.m_is_active = true;
}
@@ -567,6 +670,13 @@ hailo_status HailoNetImpl::deactivate_network_group()
GST_CHECK_EXPECTED_AS_STATUS(was_deactivated, m_element, RESOURCE, "Failed removing network, status = %d", was_deactivated.status());
if (was_deactivated.value()) {
return clear_vstreams();
}
return HAILO_SUCCESS;
}
hailo_status HailoNetImpl::clear_vstreams()
{
if (nullptr != GST_HAILOSEND(m_hailosend)->impl) {
hailo_status status = GST_HAILOSEND(m_hailosend)->impl->clear_vstreams();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing input VStreams of hailosend, status = %d", status);
@@ -576,7 +686,6 @@ hailo_status HailoNetImpl::deactivate_network_group()
hailo_status status = GST_HAILORECV(m_hailorecv)->impl->clear_vstreams();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Failed clearing output VStreams of hailorecv, status = %d", status);
}
}
return HAILO_SUCCESS;
}
@@ -596,7 +705,7 @@ gboolean HailoNetImpl::src_pad_event(GstEvent *event)
GstPadProbeReturn HailoNetImpl::sink_probe()
{
hailo_status status = activate_network_group();
hailo_status status = activate_hailonet();
GST_CHECK(HAILO_SUCCESS == status, GST_PAD_PROBE_REMOVE, m_element, RESOURCE, "Failed activating network, status = %d", status);
return GST_PAD_PROBE_REMOVE;
}
@@ -634,8 +743,33 @@ hailo_status HailoNetImpl::signal_was_flushed_event()
return m_was_flushed_event->signal();
}
static bool do_versions_match(GstHailoNet *self)
{
hailo_version_t libhailort_version = {};
auto status = hailo_get_library_version(&libhailort_version);
if (HAILO_SUCCESS != status) {
GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("Fetching libhailort version has failed! status = %d", status), (NULL));
return false;
}
bool versions_match = ((HAILORT_MAJOR_VERSION == libhailort_version.major) &&
(HAILORT_MINOR_VERSION == libhailort_version.minor) &&
(HAILORT_REVISION_VERSION == libhailort_version.revision));
if (!versions_match) {
GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("libhailort version (%d.%d.%d) does not match gsthailonet version (%d.%d.%d)",
libhailort_version.major, libhailort_version.minor, libhailort_version.revision,
HAILORT_MAJOR_VERSION, HAILORT_MINOR_VERSION, HAILORT_REVISION_VERSION), (NULL));
return false;
}
return true;
}
static void gst_hailonet_init(GstHailoNet *self)
{
if (!do_versions_match(self)) {
return;
}
auto hailonet_impl = HailoNetImpl::create(self);
if (!hailonet_impl) {
GST_ELEMENT_ERROR(self, RESOURCE, FAILED, ("Creating hailonet implementation has failed! status = %d", hailonet_impl.status()), (NULL));
@@ -700,12 +834,15 @@ static GstStateChangeReturn gst_hailonet_change_state(GstElement *element, GstSt
}
case GST_STATE_CHANGE_READY_TO_NULL:
{
// VStreams are destructed in hailosend's/hailorecv's GST_STATE_CHANGE_READY_TO_NULL (which calls 'clear_abort' on low-level streams)
// We abort streams again because deactivation of the activated network group calls flush, and it can fail on timeout unless we call abort
hailo_status status = hailonet->abort_streams();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Aborting streams has failed, status = %d\n", status);
if (HAILO_SCHEDULING_ALGORITHM_NONE == hailonet->get_props().m_scheduling_algorithm.get()) {
status = hailonet->deactivate_network_group();
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Deactivating network group has failed, status = %d\n", status);
GST_CHECK(HAILO_SUCCESS == status, GST_STATE_CHANGE_FAILURE, element, RESOURCE, "Deactivating network group failed, status = %d\n", status);
}
// Cleanup all of hailonet memory
hailonet.reset();

View File

@@ -52,7 +52,8 @@ struct HailoNetProperties final
{
public:
HailoNetProperties() : m_device_id(nullptr), m_hef_path(nullptr), m_network_name(nullptr), m_batch_size(HAILO_DEFAULT_BATCH_SIZE),
m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY)
m_is_active(false), m_device_count(0), m_vdevice_key(DEFAULT_VDEVICE_KEY), m_scheduling_algorithm(HAILO_SCHEDULING_ALGORITHM_NONE),
m_scheduler_timeout_ms(HAILO_DEFAULT_SCHEDULER_TIMEOUT_MS), m_scheduler_threshold(HAILO_DEFAULT_SCHEDULER_THRESHOLD)
{}
HailoElemProperty<gchar*> m_device_id;
@@ -62,6 +63,9 @@ public:
HailoElemProperty<gboolean> m_is_active;
HailoElemProperty<guint16> m_device_count;
HailoElemProperty<guint32> m_vdevice_key;
HailoElemProperty<hailo_scheduling_algorithm_t> m_scheduling_algorithm;
HailoElemProperty<guint32> m_scheduler_timeout_ms;
HailoElemProperty<guint32> m_scheduler_threshold;
};
class HailoNetImpl final
@@ -76,20 +80,27 @@ public:
hailo_status set_hef();
hailo_status link_elements();
hailo_status configure_network_group();
hailo_status activate_network_group();
hailo_status activate_hailonet();
hailo_status abort_streams();
hailo_status deactivate_network_group();
gboolean src_pad_event(GstEvent *event);
GstPadProbeReturn sink_probe();
gboolean is_active();
hailo_status flush();
hailo_status signal_was_flushed_event();
hailo_status deactivate_network_group();
HailoNetProperties &get_props() {
return m_props;
}
private:
void init_ghost_sink();
void init_ghost_src();
Expected<std::string> get_network_group_name(const std::string &network_name);
hailo_status clear_vstreams();
static std::atomic_uint32_t m_hailonet_count;
static std::mutex m_mutex;
GstHailoNet *m_element;

View File

@@ -359,11 +359,9 @@ static GstFlowReturn gst_hailorecv_buffer_pool_acquire_callback(GstBufferPool *p
++hailo_pool->buffers_acquired;
GstStructure *pool_config = gst_buffer_pool_get_config(pool);
GstCaps *caps = nullptr;
guint size = 0;
guint min_buffers = 0;
guint max_buffers = 0;
gboolean result = gst_buffer_pool_config_get_params(pool_config, &caps, &size, &min_buffers, &max_buffers);
gboolean result = gst_buffer_pool_config_get_params(pool_config, NULL, NULL, NULL, &max_buffers);
gst_structure_free(pool_config);
if (!result) {
g_error("Failed getting config params from buffer pool!");
return GST_FLOW_ERROR;

View File

@@ -21,7 +21,8 @@
GType gst_hailo_buffer_flag_meta_api_get_type(void)
{
static volatile GType type;
// https://github.com/vmware/open-vm-tools/commit/b2c8baeaa8ac365e1445f941cf1b80999ed89a9d
static GType type;
static const gchar *tags[] = {HAILO_BUFFER_FLAG_META_TAG, NULL};
if (g_once_init_enter(&type)) {

View File

@@ -24,7 +24,8 @@
GType gst_tensor_meta_api_get_type(void)
{
static volatile GType type;
// https://github.com/vmware/open-vm-tools/commit/b2c8baeaa8ac365e1445f941cf1b80999ed89a9d
static GType type;
static const gchar *tags[] = {TENSOR_META_TAG, NULL};
if (g_once_init_enter(&type)) {

View File

@@ -26,14 +26,16 @@ VDeviceManager NetworkGroupHandle::m_vdevice_manager;
NetworkGroupConfigManager NetworkGroupHandle::m_net_group_config_manager;
NetworkGroupActivationManager NetworkGroupHandle::m_net_group_activation_manager;
Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key)
Expected<std::shared_ptr<VDevice>> NetworkGroupHandle::create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
auto expected_device = m_vdevice_manager.create_vdevice(m_element, device_id, device_count, vdevice_key);
auto expected_device = m_vdevice_manager.create_vdevice(m_element, device_id, device_count, vdevice_key, scheduling_algorithm);
GST_CHECK_EXPECTED(expected_device, m_element, RESOURCE, "Failed creating vdevice, status = %d", expected_device.status());
return expected_device;
}
hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, const char *hef_path)
hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm, const char *hef_path)
{
if (0 == device_count) {
device_count = HAILO_DEFAULT_DEVICE_COUNT;
@@ -41,7 +43,7 @@ hailo_status NetworkGroupHandle::set_hef(const char *device_id, uint16_t device_
std::string device_id_str = (nullptr == device_id) ? "" : device_id;
auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key);
auto vdevice = create_vdevice(device_id_str, device_count, vdevice_key, scheduling_algorithm);
GST_CHECK_EXPECTED_AS_STATUS(vdevice, m_element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
m_vdevice = vdevice.release();
@@ -77,13 +79,24 @@ hailo_status NetworkGroupHandle::configure_network_group(const char *net_group_n
return HAILO_SUCCESS;
}
hailo_status NetworkGroupHandle::set_scheduler_timeout(const char *network_name, uint32_t timeout_ms)
{
return m_cng->set_scheduler_timeout(std::chrono::milliseconds(timeout_ms), network_name);
}
hailo_status NetworkGroupHandle::set_scheduler_threshold(const char *network_name, uint32_t threshold)
{
return m_cng->set_scheduler_threshold(threshold, network_name);
}
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> NetworkGroupHandle::create_vstreams(const char *network_name,
const std::vector<hailo_format_with_name_t> &output_formats)
{
GST_CHECK(nullptr != network_name, make_unexpected(HAILO_INVALID_ARGUMENT), m_element, RESOURCE, "Got nullptr in network name!");
m_network_name = network_name;
hailo_status status = m_net_group_config_manager.add_network(m_network_name, m_element);
hailo_status status = m_net_group_config_manager.add_network_to_shared_network_group(m_shared_device_id, m_network_name, m_element);
GST_CHECK(HAILO_SUCCESS == status, make_unexpected(status), m_element, RESOURCE,
"Inserting network name to configured networks has failed, status = %d", status);
@@ -198,26 +211,28 @@ Expected<bool> NetworkGroupHandle::remove_network_group()
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_vdevice(const void *element, const std::string &device_id, uint16_t device_count,
uint32_t vdevice_key)
uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (!device_id.empty()) {
return create_shared_vdevice(element, device_id);
return create_shared_vdevice(element, device_id, scheduling_algorithm);
}
if (DEFAULT_VDEVICE_KEY != vdevice_key) {
return create_shared_vdevice(element, device_count, vdevice_key);
return create_shared_vdevice(element, device_count, vdevice_key, scheduling_algorithm);
}
return create_unique_vdevice(element, device_count);
return create_unique_vdevice(element, device_count, scheduling_algorithm);
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id)
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
// If passing device_id, than device_count must be 1
const auto device_count = 1;
// If vdevice already exist, use it
auto found_vdevice = get_vdevice(device_id);
if (found_vdevice) {
auto found_vdevice = get_vdevice(device_id, scheduling_algorithm);
if (found_vdevice.status() != HAILO_NOT_FOUND) {
GST_CHECK_EXPECTED(found_vdevice, element, RESOURCE, "Failed using shared vdevice, status = %d", found_vdevice.status());
return found_vdevice.release();
}
@@ -227,40 +242,48 @@ Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const v
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = &(device_info_expected.value());
params.scheduling_algorithm = scheduling_algorithm;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
m_shared_vdevices[device_id] = vdevice_ptr;
m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key)
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
auto device_id = std::to_string(device_count) + "-" + std::to_string(vdevice_key);
// If vdevice already exist, use it
auto found_vdevice = get_vdevice(device_id);
if (found_vdevice) {
auto found_vdevice = get_vdevice(device_id, scheduling_algorithm);
if (found_vdevice.status() != HAILO_NOT_FOUND) {
GST_CHECK_EXPECTED(found_vdevice, element, RESOURCE, "Failed using shared vdevice, status = %d", found_vdevice.status());
return found_vdevice.release();
}
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = nullptr;
params.scheduling_algorithm = scheduling_algorithm;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
std::shared_ptr<VDevice> vdevice_ptr = std::move(vdevice.release());
m_shared_vdevices[device_id] = vdevice_ptr;
m_shared_vdevices_scheduling_algorithm[device_id] = scheduling_algorithm;
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count)
Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const void *element, uint16_t device_count,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
hailo_vdevice_params_t params = {};
params.device_count = device_count;
params.device_infos = nullptr;
params.scheduling_algorithm = scheduling_algorithm;
auto vdevice = VDevice::create(params);
GST_CHECK_EXPECTED(vdevice, element, RESOURCE, "Failed creating vdevice, status = %d", vdevice.status());
@@ -270,12 +293,23 @@ Expected<std::shared_ptr<VDevice>> VDeviceManager::create_unique_vdevice(const v
return vdevice_ptr;
}
Expected<std::shared_ptr<VDevice>> VDeviceManager::get_vdevice(const std::string &device_id)
Expected<std::shared_ptr<VDevice>> VDeviceManager::get_vdevice(const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm)
{
auto found = m_shared_vdevices.find(device_id);
if (found == m_shared_vdevices.end()) {
return make_unexpected(HAILO_NOT_FOUND);
}
// shared_vdevice is found, verify the requested scheduling_algorithm
assert(m_shared_vdevices_scheduling_algorithm.end() != m_shared_vdevices_scheduling_algorithm.find(device_id));
if (scheduling_algorithm != m_shared_vdevices_scheduling_algorithm[device_id]) {
auto status = HAILO_INVALID_OPERATION;
g_warning("Shared vdevice with the same credentials is already exists (%s) but with a different scheduling-algorithm (requested: %d, exists: %d), status = %d",
device_id.c_str(), scheduling_algorithm, m_shared_vdevices_scheduling_algorithm[device_id], status);
return make_unexpected(HAILO_INVALID_OPERATION);
}
auto vdevice_cpy = found->second;
return vdevice_cpy;
}
@@ -300,15 +334,24 @@ Expected<std::shared_ptr<ConfiguredNetworkGroup>> NetworkGroupConfigManager::con
return std::move(network_group_list->at(0));
}
hailo_status NetworkGroupConfigManager::add_network(const std::string &network_name, const GstElement *owner_element)
hailo_status NetworkGroupConfigManager::add_network_to_shared_network_group(const std::string &shared_device_id, const std::string &network_name,
const GstElement *owner_element)
{
std::unique_lock<std::mutex> lock(m_mutex);
auto found = m_configured_networks.find(network_name);
GST_CHECK(found == m_configured_networks.end(), HAILO_INVALID_OPERATION, owner_element, RESOURCE,
"Network %s was already configured by %s!", network_name.c_str(), found->second.c_str());
if (shared_device_id.empty()) {
// the device is unique so we don't need to share anything
return HAILO_SUCCESS;
}
m_configured_networks[network_name] = GST_ELEMENT_NAME(owner_element);
auto found_by_device = m_configured_networks.find(shared_device_id);
if (found_by_device != m_configured_networks.end()) {
auto found_network = found_by_device->second.find(network_name);
GST_CHECK(found_network == found_by_device->second.end(), HAILO_INVALID_OPERATION, owner_element, RESOURCE,
"Network %s was already configured by %s by the same device!", network_name.c_str(), found_network->second.c_str());
}
m_configured_networks[shared_device_id][network_name] = GST_ELEMENT_NAME(owner_element);
return HAILO_SUCCESS;
}

View File

@@ -31,23 +31,29 @@
class VDeviceManager final
{
public:
VDeviceManager() : m_shared_vdevices(), m_unique_vdevices() {}
VDeviceManager() : m_shared_vdevices(), m_shared_vdevices_scheduling_algorithm(), m_unique_vdevices() {}
Expected<std::shared_ptr<VDevice>> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
Expected<std::shared_ptr<VDevice>> create_vdevice(const void *element, const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm);
private:
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id);
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key);
Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count);
Expected<std::shared_ptr<VDevice>> get_vdevice(const std::string &device_id);
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, const std::string &device_id,
hailo_scheduling_algorithm_t scheduling_algorithm);
Expected<std::shared_ptr<VDevice>> create_shared_vdevice(const void *element, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm);
Expected<std::shared_ptr<VDevice>> create_unique_vdevice(const void *element, uint16_t device_count,
hailo_scheduling_algorithm_t scheduling_algorithm);
Expected<std::shared_ptr<VDevice>> get_vdevice(const std::string &device_id, hailo_scheduling_algorithm_t scheduling_algorithm);
/* Contains only the shared vdevices (either created by bdf, or with device-count && vdevice-key)
Keys are either "<BDF>" or "<device_count>-<vdevice_key>" */
std::unordered_map<std::string, std::shared_ptr<VDevice>> m_shared_vdevices;
std::unordered_map<std::string, hailo_scheduling_algorithm_t> m_shared_vdevices_scheduling_algorithm; // Used to check that 2 shared vdevices gets the same scheduling-algorithm
std::vector<std::shared_ptr<VDevice>> m_unique_vdevices;
std::mutex m_mutex;
};
using device_id_t = std::string;
using network_name_t = std::string;
using hailonet_name_t = std::string;
@@ -58,7 +64,8 @@ public:
Expected<std::shared_ptr<ConfiguredNetworkGroup>> configure_network_group(const void *element, const std::string &device_id,
const char *network_group_name, uint16_t batch_size, std::shared_ptr<VDevice> &vdevice, std::shared_ptr<Hef> hef,
NetworkGroupsParamsMap &net_groups_params_map);
hailo_status add_network(const std::string &network_name, const GstElement *owner_element);
hailo_status add_network_to_shared_network_group(const std::string &shared_device_id, const std::string &network_name,
const GstElement *owner_element);
private:
static std::string get_configure_string(const std::string &device_id, const char *network_group_name, uint16_t batch_size);
@@ -69,7 +76,7 @@ private:
// TODO: change this map to store only the shared network_groups (used by multiple hailonets with the same vdevices)
std::unordered_map<std::string, std::shared_ptr<ConfiguredNetworkGroup>> m_configured_net_groups;
std::unordered_map<network_name_t, hailonet_name_t> m_configured_networks;
std::unordered_map<device_id_t, std::unordered_map<network_name_t, hailonet_name_t>> m_configured_networks;
std::mutex m_mutex;
};
@@ -96,7 +103,8 @@ public:
NetworkGroupHandle(const GstElement *element) : m_element(element), m_shared_device_id(), m_net_group_name(), m_network_name(), m_batch_size(0),
m_vdevice(nullptr), m_hef(nullptr), m_cng(nullptr), m_ang(nullptr) {}
hailo_status set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, const char *hef_path);
hailo_status set_hef(const char *device_id, uint16_t device_count, uint32_t vdevice_key, hailo_scheduling_algorithm_t scheduling_algorithm,
const char *hef_path);
hailo_status configure_network_group(const char *net_group_name, uint16_t batch_size);
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> create_vstreams(const char *network_name,
const std::vector<hailo_format_with_name_t> &output_formats);
@@ -104,6 +112,10 @@ public:
hailo_status abort_streams();
Expected<bool> remove_network_group();
hailo_status set_scheduler_timeout(const char *network_name, uint32_t timeout_ms);
hailo_status set_scheduler_threshold(const char *network_name, uint32_t threshold);
std::shared_ptr<Hef> hef()
{
return m_hef;
@@ -111,13 +123,14 @@ public:
private:
Expected<NetworkGroupsParamsMap> get_configure_params(Hef &hef, const char *net_group_name, uint16_t batch_size);
Expected<std::shared_ptr<VDevice>> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key);
Expected<std::shared_ptr<VDevice>> create_vdevice(const std::string &device_id, uint16_t device_count, uint32_t vdevice_key,
hailo_scheduling_algorithm_t scheduling_algorithm);
static VDeviceManager m_vdevice_manager;
static NetworkGroupConfigManager m_net_group_config_manager;
static NetworkGroupActivationManager m_net_group_activation_manager;
const GstElement *m_element;
std::string m_shared_device_id;
std::string m_shared_device_id; // empty string when using unique device
std::string m_net_group_name;
std::string m_network_name;
uint16_t m_batch_size;

View File

@@ -1 +1,9 @@
add_subdirectory(src)
# copy files to venv
if(HAILO_BUILD_PYHAILORT_VENV)
add_custom_target(pyhailort_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:_pyhailort> ${CMAKE_CURRENT_LIST_DIR}/platform/hailo_platform/pyhailort/
)
add_dependencies(pyhailort_venv _pyhailort)
endif()

View File

@@ -1,6 +1,6 @@
from hailo_platform import (HEF, PcieDevice, ConfigureParams, InferVStreams, InputVStreamParams,
OutputVStreamParams, FormatType)
from hailo_platform.drivers.hailort.pyhailort import HailoStreamInterface
from hailo_platform.pyhailort.pyhailort import HailoStreamInterface
import numpy as np
import argparse
@@ -26,5 +26,7 @@ def main():
with network_group.activate(network_group_params):
_ = infer_pipeline.infer(input_data)
print('Inference ran successfully')
if __name__ == '__main__':
main()

View File

@@ -4,40 +4,10 @@ import sys
import pathlib
import pprint
from hailo_platform.common.paths_manager.version import get_version
from hailo_platform.common.paths_manager.paths import PackingInfo, PackingStatus
class MissingPyHRTLib(Exception):
pass
# This hack checks which modules the user has on his computer.
# packing status set to "packed_client" if it can't import the PLATFORM_INTERNALS module
# it set the packing status to "standalone_platform" if it can't import the SDK_COMMON module
try:
import hailo_platform_internals # noqa F401
except ImportError:
PackingInfo().status = PackingStatus.packed_client
try:
import hailo_sdk_common # noqa F401
except:
PackingInfo().status = PackingStatus.standalone_platform
# This hack only affects internals users with hailo_validation installed.
# It changes the packing status to PACKED if it thinks SDK was installed from
# wheel.
try:
import hailo_validation # noqa F401
if 'site-packages/hailo_sdk' in __path__[0] :
PackingInfo().status = PackingStatus.packed_client
except ImportError:
pass
# Must appear before other imports:
def join_drivers_path(path):
_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -45,11 +15,8 @@ def join_drivers_path(path):
from hailo_platform.tools.udp_rate_limiter import UDPRateLimiter
from hailo_platform.drivers.hw_object import PcieDevice, EthernetDevice
from hailo_platform.drivers.hailo_controller.power_measurement import (DvmTypes,
PowerMeasurementTypes,
SamplingPeriod, AveragingFactor)
from hailo_platform.drivers.hailort.pyhailort import (HEF, ConfigureParams,
from hailo_platform.pyhailort.hw_object import PcieDevice, EthernetDevice
from hailo_platform.pyhailort.pyhailort import (HEF, ConfigureParams,
FormatType, FormatOrder,
MipiDataTypeRx, MipiPixelsPerClock,
MipiClockSelection, MipiIspImageInOrder,
@@ -57,7 +24,8 @@ from hailo_platform.drivers.hailort.pyhailort import (HEF, ConfigureParams,
Endianness, HailoStreamInterface,
InputVStreamParams, OutputVStreamParams,
InputVStreams, OutputVStreams,
InferVStreams, HailoStreamDirection, HailoFormatFlags, HailoCpuId, VDevice)
InferVStreams, HailoStreamDirection, HailoFormatFlags, HailoCpuId, VDevice,
DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex)
def _verify_pyhailort_lib_exists():
python_version = "".join(str(i) for i in sys.version_info[:2])
@@ -66,16 +34,29 @@ def _verify_pyhailort_lib_exists():
"nt": "pyd", # Windows
}[os.name]
path = f"{__path__[0]}/drivers/hailort/"
path = f"{__path__[0]}/pyhailort/"
if next(pathlib.Path(path).glob(f"_pyhailort*.{lib_extension}"), None) is None:
raise MissingPyHRTLib(f"{path} should include a _pyhailort library (_pyhailort*{python_version}*.{lib_extension}). Includes: {pprint.pformat(list(pathlib.Path(path).iterdir()))}")
_verify_pyhailort_lib_exists()
def get_version(package_name):
# See: https://packaging.python.org/guides/single-sourcing-package-version/ (Option 5)
# We assume that the installed package is actually the same one we import. This assumption may
# break in some edge cases e.g. if the user modifies sys.path manually.
# hailo_platform package has been renamed to hailort, but the import is still hailo_platform
if package_name == "hailo_platform":
package_name = "hailort"
try:
import pkg_resources
return pkg_resources.get_distribution(package_name).version
except:
return 'unknown'
__version__ = get_version('hailo_platform')
__all__ = ['EthernetDevice', 'DvmTypes', 'PowerMeasurementTypes',
'SamplingPeriod', 'AveragingFactor', 'UDPRateLimiter', 'PcieDevice', 'HEF',
'SamplingPeriod', 'AveragingFactor', 'MeasurementBufferIndex', 'UDPRateLimiter', 'PcieDevice', 'HEF',
'ConfigureParams', 'FormatType', 'FormatOrder', 'MipiDataTypeRx', 'MipiPixelsPerClock', 'MipiClockSelection',
'MipiIspImageInOrder', 'MipiIspImageOutDataType', 'join_drivers_path', 'IspLightFrequency', 'HailoPowerMode',
'Endianness', 'HailoStreamInterface', 'InputVStreamParams', 'OutputVStreamParams',

View File

@@ -1,27 +0,0 @@
#!/usr/bin/env python
import six
from io import IOBase
# Based on: https://portingguide.readthedocs.io/en/latest/builtins.html#removed-file
try:
# Python 2
file_types = (file, IOBase,)
except NameError:
# "file" isn't a built-in type in Python 3
file_types = (IOBase,)
# Exporting types and functions from six
string_types = six.string_types
integer_types = six.integer_types
class_types = six.class_types
text_type = six.text_type
binary_type = six.binary_type
def ensure_binary(s, encoding='utf-8', errors='strict'):
return six.ensure_binary(s, encoding=encoding, errors=errors)
def ensure_str(s, encoding='utf-8', errors='strict'):
return six.ensure_str(s, encoding=encoding, errors=errors)
def ensure_text(s, encoding='utf-8', errors='strict'):
return six.ensure_text(s, encoding=encoding, errors=errors)

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env python
import os
from configparser import ConfigParser
from hailo_platform.common.paths_manager.paths import PackingInfo, PackingStatus, SDKPaths
from hailo_platform.paths_manager.paths import PlatformPaths
class ConfigFileNotFoundException(Exception):
pass
def get_home_hailo_dir():
return os.path.expanduser('~/.hailo')
def get_parsed_config_from_path(config_path=None):
actual_config_path = _get_config_path_with_default(config_path)
config = ConfigParser()
with open(actual_config_path, 'r') as config_file:
config.read_file(config_file)
return config
def _get_config_path_with_default(config_path=None):
if config_path is not None and os.path.isfile(config_path):
return config_path
default_path = _get_config_path()
if os.path.isfile(default_path):
return default_path
raise ConfigFileNotFoundException('Could not find configuration file at default path: {}.'.format(default_path))
def _get_config_path():
config_file_name = 'config'
if PackingInfo().status in [PackingStatus.unpacked]:
full_path = os.path.join(SDKPaths().join_sdk('../'), config_file_name)
if os.path.exists(full_path):
return full_path
#This is a CI nightly workaround because we are in unpack mode but installing whl's
#In this case SDKPaths() is inside the site packages and not the sdk root. the workaround is to look for local dir
elif os.path.exists(config_file_name):
return config_file_name
elif PackingInfo().status in [PackingStatus.standalone_platform]:
full_path = os.path.join(PlatformPaths().join_platform('../../'), config_file_name)
if os.path.exists(full_path) and os.path.isfile(full_path):
return full_path
elif os.path.exists(config_file_name):
return config_file_name
return os.path.join(get_home_hailo_dir(), config_file_name)

View File

@@ -1,207 +0,0 @@
#!/usr/bin/env python
from builtins import object
import os
import shutil
import copy
from enum import Enum
from hailo_platform.common.logger.logger import default_logger
from future.utils import with_metaclass
logger = default_logger()
class ConfigStageNotSetException(Exception):
pass
class PackagingException(Exception):
pass
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class PackingStatus(Enum):
unpacked = 'unpacked'
packed_server = 'packed_server'
packed_client = 'packed_client'
standalone_platform = 'standalone_platform'
class PackingInfo(with_metaclass(Singleton, object)):
def __init__(self):
self._status = PackingStatus.unpacked
self._has_graphviz = True
def is_packed(self):
return self._status not in [PackingStatus.unpacked]
@property
def status(self):
return self._status
@status.setter
def status(self, val):
self._status = val
@property
def has_graphviz(self):
return self._has_graphviz
@has_graphviz.setter
def has_graphviz(self, val):
self._has_graphviz = val
class SDKPaths(with_metaclass(Singleton, object)):
DEFAULT_BUILD_DIR = 'build'
def __init__(self):
self._build_dir_name = type(self).DEFAULT_BUILD_DIR
self._build_dir_path = '.'
self._custom_build_dir = None
@property
def _sdk_path(self):
packaging_status = PackingInfo().status
if packaging_status == PackingStatus.packed_server:
import hailo_sdk_common
return os.path.dirname(hailo_sdk_common.__path__[0])
if packaging_status == PackingStatus.packed_client:
return ''
if packaging_status == PackingStatus.standalone_platform:
raise PackagingException(
'the packaging status is \'standalone_platform\', and there was a call to a sdk method')
import hailo_sdk_common
return os.path.join(os.path.dirname(os.path.dirname(hailo_sdk_common.__path__[0])), 'sdk_server')
@property
def custom_build_dir(self):
return self._custom_build_dir
@custom_build_dir.setter
def custom_build_dir(self, custom_build_dir):
self._custom_build_dir = custom_build_dir
def join_sdk(self, path):
return os.path.join(self._sdk_path, path)
def join_sdk_common(self, path):
import hailo_sdk_common
if PackingInfo().status == PackingStatus.packed_server:
return self.join_sdk(os.path.join('hailo_sdk_common', path))
return os.path.join(os.path.abspath(hailo_sdk_common.__path__[0]), path)
def set_client_build_dir_path(self):
if PackingInfo().status == PackingStatus.unpacked:
self._build_dir_path = '../sdk_client'
def set_server_build_dir_path(self):
if PackingInfo().status == PackingStatus.unpacked:
self._build_dir_path = '../sdk_server'
def set_build_dir(self, build_dir_name=None, clean=False):
self._build_dir_name = build_dir_name if build_dir_name is not None else type(self).DEFAULT_BUILD_DIR
logger.debug('Build dir name: {}'.format(self._build_dir_name))
build_dir = self.build_dir
if os.path.exists(build_dir):
if clean:
logger.debug('Deleting build dir : {}'.format(build_dir))
shutil.rmtree(build_dir)
self._make_build_dir(build_dir)
return
self._make_build_dir(build_dir)
@property
def build_dir(self):
if self._custom_build_dir:
return self._custom_build_dir
return os.path.join(self._sdk_path, self._build_dir_path, self._build_dir_name)
def join_build_sdk(self, path):
build_dir = self.build_dir
if os.path.exists(build_dir):
return os.path.join(build_dir, path)
logger.debug('Creating build dir : {}'.format(build_dir))
self._make_build_dir(build_dir)
return os.path.join(build_dir, path)
def _make_build_dir(self, build_dir):
os.makedirs(build_dir)
class BaseConfigDirs(object):
DIRS_BUILD_ONLY = {
'outputs_dir': ['outputs'],
'bin_dir': ['bin'],
'weights_dir': ['data', 'weights'],
'inputs_dir': ['data', 'inputs'],
}
DIRS_SDK_ONLY = {}
DIRS_BOTH = {}
def __init__(self, hw_arch):
self._hw_arch = hw_arch.name
self._paths = SDKPaths()
self._dirs = {}
for d in [type(self).DIRS_BUILD_ONLY, type(self).DIRS_SDK_ONLY, type(self).DIRS_BOTH]:
self._dirs.update(self._format_dirs(d))
def get_dir(self, name, in_build=True):
return self._join_base(self._dirs[name], in_build)
def _format_dirs(self, input_dirs):
result = {}
for name, dir_path in input_dirs.items():
result[name] = os.path.join(*dir_path).format(hw_arch=self._hw_arch)
return result
def _join_base(self, path, in_build=True):
base_dir = self._paths.build_dir if in_build else 'microcode'
whole_path = os.path.join(base_dir, path)
return self._paths.join_sdk(whole_path)
@property
def build_dirs_keys(self):
return list(type(self).DIRS_BUILD_ONLY.keys()) + list(type(self).DIRS_BOTH.keys())
class BaseConfigPaths(BaseConfigDirs):
PATHS = {
'bin': ['{bin_dir}', '{network_name}.mem'],
}
def __init__(self, hw_arch, model_name):
super(BaseConfigPaths, self).__init__(hw_arch)
self._model_name = model_name
self._stage = None
self._stage_only = False
def set_stage(self, stage, stage_only=False):
self._stage = stage
self._stage_only = stage_only
def get_path(self, path_name, in_build=True):
template = os.path.join(*type(self).PATHS[path_name])
if self._stage is None and '{network_name}' in template:
raise ConfigStageNotSetException('Set the stage before trying to get paths')
format_dict = copy.deepcopy(self._dirs)
format_dict['model_name'] = self._model_name
if self._stage_only:
format_dict['network_name'] = self._stage
else:
format_dict['network_name'] = '{model_name}.{stage}'.format(
model_name=self._model_name, stage=self._stage
)
config_path = template.format(**format_dict)
return self._join_base(config_path, in_build)

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
def get_version(package_name):
# See: https://packaging.python.org/guides/single-sourcing-package-version/ (Option 5)
# We assume that the installed package is actually the same one we import. This assumption may
# break in some edge cases e.g. if the user modifies sys.path manually.
# hailo_platform package has been renamed to hailort, but the import is still hailo_platform
if package_name == "hailo_platform":
package_name = "hailort"
try:
import pkg_resources
return pkg_resources.get_distribution(package_name).version
except:
return 'unknown'

View File

@@ -1,111 +0,0 @@
#!/usr/bin/env python
from builtins import object
import json
from contextlib2 import contextmanager
class InferenceTargetException(Exception):
"""Raised when an error related to the inference target has occurred."""
pass
class InferenceTargets(object):
"""Enum-like class with all inference targets supported by the Hailo SDK.
See the classes themselves for details about each target.
"""
UNINITIALIZED = 'uninitialized'
SDK_NATIVE = 'sdk_native'
SDK_NATIVE_CLIPPED = 'sdk_native_clipped'
SDK_NUMERIC = 'sdk_numeric'
SDK_DEBUG_PRECISE_NUMERIC = 'sdk_debug_precise_numeric'
SDK_PARTIAL_NUMERIC = 'sdk_partial_numeric'
SDK_FINE_TUNE = 'sdk_fine_tune'
SDK_MIXED = 'sdk_mixed'
HW_SIMULATION = 'hw_sim'
HW_SIMULATION_MULTI_CLUSTER = 'hw_sim_mc'
FPGA = 'fpga'
UDP_CONTROLLER = 'udp'
PCIE_CONTROLLER = 'pcie'
HW_DRY = 'hw_dry'
HW_DRY_UPLOAD = 'hw_dry_upload'
UV_WORKER = 'uv'
DANNOX = 'dannox'
class InferenceObject(object):
"""Represents a target that can run models inference. The target can be either software based
(eventually running on CPU/GPU), or Hailo hardware based.
.. note:: This class should not be used directly. Use only its inherited classes.
"""
NAME = InferenceTargets.UNINITIALIZED
IS_NUMERIC = False
IS_HARDWARE = False
IS_SIMULATION = False
def __new__(cls, *args, **kwargs):
if cls.NAME == InferenceTargets.UNINITIALIZED:
raise InferenceTargetException(
'{} is an abstract target and cannot be used directly.'.format(cls.__name__))
# object's __new__() takes no parameters
return super(type(cls), cls).__new__(cls)
def __init__(self):
"""Inference object constructor."""
self._is_device_used = False
def __eq__(self, other):
return type(self).NAME == other
# TODO: Required for Python2 BW compatibility (SDK-10038)
# This impl' comes by default in Python3
def __ne__(self, other):
return not self.__eq__(other)
@contextmanager
def use_device(self, *args, **kwargs):
"""A context manager that should wrap any usage of the target."""
self._is_device_used = True
yield
self._is_device_used = False
@property
def name(self):
"""str: The name of this target. Valid values are defined by
:class:`InferenceObject <hailo_sdk_common.targets.inference_targets.InferenceTargets>`.
"""
return type(self).NAME
@property
def is_numeric(self):
"""bool: Determines whether this target is working in numeric mode.
"""
return type(self).IS_NUMERIC
@property
def is_hardware(self):
"""bool: Determines whether this target runs on a physical hardware device.
"""
return type(self).IS_HARDWARE
@property
def is_simulation(self):
"""bool: Determines whether this target is used for HW simulation.
"""
return type(self).IS_SIMULATION
def _get_json_dict(self):
json_dict = {'name': self.name,
'is_numeric': self.is_numeric,
'is_hardware': self.is_hardware,
'is_simulation': self.is_simulation}
return json_dict
def to_json(self):
"""Get a JSON representation of this object.
Returns:
str: A JSON dump.
"""
return json.dumps(self._get_json_dict())

View File

@@ -1,6 +1,4 @@
#!/usr/bin/env python
""":class:`~hailo_platform.drivers.hw_object.HailoHWObject` is the high level base class of the
platform API. :class:`~hailo_platform.drivers.hw_object.PcieDevice` inherits from it
and implements control and dataflow over PCIe.
"""
from warnings import warn
warn("Importing from 'hailo_platform.drivers' is deprecated, One should import from 'hailo_platform' module directly.", DeprecationWarning, stacklevel=2)

View File

@@ -1,655 +1 @@
#!/usr/bin/env python
"""Control operations for the Hailo hardware device."""
import struct
from builtins import object
from abc import ABCMeta, abstractmethod
from future.utils import with_metaclass
from hailo_platform.drivers.hailo_controller.hailo_control_protocol import HailoResetTypes, DeviceArchitectureTypes
from hailo_platform.drivers.hailo_controller.power_measurement import SamplingPeriod, AveragingFactor, DvmTypes, PowerMeasurementTypes, DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS
from hailo_platform.drivers.hailort.pyhailort import Control, InternalPcieDevice
from hailo_platform.common.logger.logger import default_logger
class ControlObjectException(Exception):
"""Raised on illegal ContolObject operation."""
pass
class FirmwareUpdateException(Exception):
pass
class HailoControl(with_metaclass(ABCMeta, object)):
"""Control object that sends control operations to a Hailo hardware device."""
def __init__(self):
"""Initializes a new HailoControl object."""
self._logger = default_logger()
self._controller = None
@abstractmethod
def open(self):
"""Initializes the resources needed for using a control device."""
pass
@abstractmethod
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def configure(self, hef, configure_params_by_name={}):
"""
Configures device from HEF object.
Args:
hef (:class:`~hailo_platform.drivers.hailort.pyhailort.HEF`): HEF to configure the
device from.
configure_params_by_name (dict, optional): Maps between each net_group_name to
configure_params. In case of a mismatch with net_groups_names, default params will
be used.
"""
return self._controller.configure_device_from_hef(hef, configure_params_by_name)
@abstractmethod
def chip_reset(self):
"""Resets the device (chip reset)."""
pass
@abstractmethod
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte.
"""
pass
@abstractmethod
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
pass
class HcpControl(HailoControl):
"""Control object that uses the HCP protocol for controlling the device."""
WORD_SIZE = 4
def __init__(self):
super(HcpControl, self).__init__()
@property
def device_id(self):
"""Getter for the device_id.
Returns:
str: A string ID of the device. BDF for PCIe devices, MAC address for Ethernet devices, "Core" for core devices.
"""
return self._device_id
def open(self):
"""Initializes the resources needed for using a control device."""
pass
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def chip_reset(self):
"""Resets the device (chip reset)."""
return self._controller.reset(reset_type=HailoResetTypes.CHIP)
def nn_core_reset(self):
"""Resets the nn_core."""
return self._controller.reset(reset_type=HailoResetTypes.NN_CORE)
def soft_reset(self):
"""reloads the device firmware (soft reset)"""
return self._controller.reset(reset_type=HailoResetTypes.SOFT)
def forced_soft_reset(self):
"""reloads the device firmware (forced soft reset)"""
return self._controller.reset(reset_type=HailoResetTypes.FORCED_SOFT)
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip. Byte order isn't changed. The core uses little-endian
byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte
"""
return self._controller.read_memory(address, data_length)
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip. Byte order isn't changed. The core uses little-endian byte
order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
return self._controller.write_memory(address, data_buffer)
def power_measurement(self, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Perform a single power measurement on an Hailo chip. It works with the default settings
where the sensor returns a new value every 2.2 ms without averaging the values.
Args:
dvm (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Returns:
float: The measured power. \n
For :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power. For all supported
measurement types, please look at
:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
return self._controller.power_measurement(dvm, measurement_type)
def start_power_measurement(self, delay=DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS, averaging_factor=AveragingFactor.AVERAGE_256, sampling_period=SamplingPeriod.PERIOD_1100us):
"""Start performing a long power measurement.
Args:
delay (int): Amount of time between each measurement interval (in milliseconds) This
time period is sleep time of the core. The default value depends on the other
default values, plus a factor of 20 percent.
averaging_factor (:class:`~hailo_platform.drivers.hailort.pyhailort.AveragingFactor`):
Number of samples per time period, sensor configuration value.
sampling_period (:class:`~hailo_platform.drivers.hailort.pyhailort.SamplingPeriod`):
Related conversion time, sensor configuration value. The sensor samples the power
every ``sampling_period`` [ms] and averages every ``averaging_factor`` samples. The
sensor provides a new value every: 2 * sampling_period * averaging_factor [ms]. The
firmware wakes up every ``delay`` [ms] and checks the sensor. If there is a new
value to read from the sensor, the firmware reads it. Note that the average
calculated by the firmware is "average of averages", because it averages values
that have already been averaged by the sensor.
"""
return self._controller.start_power_measurement(delay, averaging_factor, sampling_period)
def stop_power_measurement(self):
"""Stop performing a long power measurement. Deletes all saved results from the firmware.
Calling the function eliminates the start function settings for the averaging the samples,
and returns to the default values, so the sensor will return a new value every 2.2 ms
without averaging values.
"""
return self._controller.stop_power_measurement()
def set_power_measurement(self, index, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Set parameters for long power measurement on an Hailo chip.
Args:
index (int): Index of the buffer on the firmware the data would be saved at.
dvm (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.drivers.hailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Note:
This function can perform measurements for more than just power. For all supported measurement types
view :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`
"""
return self._controller.set_power_measurement(index, dvm, measurement_type)
def get_power_measurement(self, index, should_clear=True):
"""Read measured power from a long power measurement
Args:
index (int): Index of the buffer on the firmware the data would be saved at.
should_clear (bool): Flag indicating if the results saved at the firmware will be deleted after reading.
Returns:
:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementData`:
Object containing measurement data \n
For :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power.
For all supported measurement types view
:class:`~hailo_platform.drivers.hailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
return self._controller.get_power_measurement(
index,
should_clear=should_clear)
def _examine_user_config(self):
return self._controller.examine_user_config()
def read_user_config(self):
"""Read the user configuration section as binary data.
Returns:
str: User config as a binary buffer.
"""
return self._controller.read_user_config()
def write_user_config(self, configuration):
"""Write the user configuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
return self._controller.write_user_config(configuration)
def _erase_user_config(self):
return self._controller.erase_user_config()
def read_board_config(self):
"""Read the board configuration section as binary data.
Returns:
str: Board config as a binary buffer.
"""
return self._controller.read_board_config()
def write_board_config(self, configuration):
"""Write the static confuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
return self._controller.write_board_config(configuration)
def identify(self):
"""Gets the Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
return self._controller.identify()
def core_identify(self):
"""Gets the Core Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
return self._controller.core_identify()
def set_fw_logger(self, level, interface_mask):
"""Configure logger level and interface of sending.
Args:
level (FwLoggerLevel): The minimum logger level.
interface_mask (int): Output interfaces (mix of FwLoggerInterface).
"""
return self._controller.set_fw_logger(level, interface_mask)
def set_throttling_state(self, should_activate):
"""Change throttling state of temperature protection component.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
return self._controller.set_throttling_state(should_activate)
def get_throttling_state(self):
"""Get the current throttling state of temperature protection component.
Returns:
bool: true if temperature throttling is enabled, false otherwise.
"""
return self._controller.get_throttling_state()
def _set_overcurrent_state(self, should_activate):
"""Control whether the overcurrent protection is enabled or disabled.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
return self._controller._set_overcurrent_state(should_activate)
def _get_overcurrent_state(self):
"""Get the overcurrent protection state.
Returns:
bool: true if overcurrent protection is enabled, false otherwise.
"""
return self._controller._get_overcurrent_state()
def i2c_write(self, slave, register_address, data):
"""Write data to an I2C slave.
Args:
slave (:class:`hailo_platform.drivers.hailo_controller.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register to which the data will be written.
data (str): The data that will be written.
"""
return self._controller.i2c_write(slave, register_address, data)
def i2c_read(self, slave, register_address, data_length):
"""Read data from an I2C slave.
Args:
slave (:class:`hailo_platform.drivers.hailo_controller.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register from which the data will be read.
data_length (int): The number of bytes to read.
Returns:
str: Data read from the I2C slave.
"""
return self._controller.i2c_read(slave, register_address, data_length)
def read_register(self, address):
"""Read the value of a register from a given address.
Args:
address (int): Address to read register from.
Returns:
int: Value of the register
"""
register_value, = struct.unpack('!I', self.read_memory(address, type(self).WORD_SIZE))
return register_value
def set_bit(self, address, bit_index):
"""Set (turn on) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be set.
"""
register_value = self.read_register(address)
register_value |= 1 << bit_index
self.write_memory(address, struct.pack('!I', register_value))
def reset_bit(self, address, bit_index):
"""Reset (turn off) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be reset.
"""
register_value = self.read_register(address)
register_value &= ~(1 << bit_index)
self.write_memory(address, struct.pack('!I', register_value))
def firmware_update(self, firmware_binary, should_reset=True):
"""Update firmware binary on the flash.
Args:
firmware_binary (bytes): firmware binary stream.
should_reset (bool): Should a reset be performed after the update (to load the new firmware)
"""
return self._controller.firmware_update(firmware_binary, should_reset)
def second_stage_update(self, second_stage_binary):
"""Update second stage binary on the flash
Args:
second_stage_binary (bytes): second stage binary stream.
"""
return self._controller.second_stage_update(second_stage_binary)
def store_sensor_config(self, section_index, reset_data_size, sensor_type, config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor configuration to Hailo chip flash memory.
Args:
section_index (int): Flash section index to write to. [0-6]
reset_data_size (int): Size of reset configuration.
sensor_type (:class:`~hailo_platform.drivers.hailort.pyhailort.SensorConfigTypes`): Sensor type.
config_file_path (str): Sensor configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
return self._controller.sensor_store_config(section_index, reset_data_size, sensor_type, config_file_path,
config_height, config_width, config_fps, config_name)
def store_isp_config(self, reset_config_size, isp_static_config_file_path, isp_runtime_config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor isp configuration to Hailo chip flash memory.
Args:
reset_config_size (int): Size of reset configuration.
isp_static_config_file_path (str): Sensor isp static configuration file path.
isp_runtime_config_file_path (str): Sensor isp runtime configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
return self._controller.store_isp_config(reset_config_size, config_height, config_width,
config_fps, isp_static_config_file_path, isp_runtime_config_file_path, config_name)
def get_sensor_sections_info(self):
"""Get sensor sections info from Hailo chip flash memory.
Returns:
Sensor sections info read from the chip flash memory.
"""
return self._controller.sensor_get_sections_info()
def sensor_set_generic_i2c_slave(self, slave_address, register_address_size, bus_index, should_hold_bus, endianness):
"""Set a generic I2C slave for sensor usage.
Args:
sequence (int): Request/response sequence.
slave_address (int): The address of the I2C slave.
register_address_size (int): The size of the offset (in bytes).
bus_index (int): The number of the bus the I2C slave is behind.
should_hold_bus (bool): Hold the bus during the read.
endianness (:class:`~hailo_platform.drivers.hailort.pyhailort.Endianness`):
Big or little endian.
"""
return self._controller.sensor_set_generic_i2c_slave(slave_address, register_address_size, bus_index, should_hold_bus, endianness)
def set_sensor_i2c_bus_index(self, sensor_type, i2c_bus_index):
"""Set the I2C bus to which the sensor of the specified type is connected.
Args:
sensor_type (:class:`~hailo_platform.drivers.hailort.pyhailort.SensorConfigTypes`): The sensor type.
i2c_bus_index (int): The I2C bus index of the sensor.
"""
return self._controller.sensor_set_i2c_bus_index(sensor_type, i2c_bus_index)
def load_and_start_sensor(self, section_index):
"""Load the configuration with I2C in the section index.
Args:
section_index (int): Flash section index to load config from. [0-6]
"""
return self._controller.sensor_load_and_start_config(section_index)
def reset_sensor(self, section_index):
"""Reset the sensor that is related to the section index config.
Args:
section_index (int): Flash section index to reset. [0-6]
"""
return self._controller.sensor_reset(section_index)
def wd_enable(self, cpu_id):
"""Enable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
self._controller.wd_enable(cpu_id)
def wd_disable(self, cpu_id):
"""Disable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
self._controller.wd_disable(cpu_id)
def wd_config(self, cpu_id, wd_cycles, wd_mode):
"""Configure a firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
wd_cycles (int): number of cycles until watchdog is triggered.
wd_mode (int): 0 - HW/SW mode, 1 - HW only mode
"""
return self._controller.wd_config(cpu_id, wd_cycles, wd_mode)
def previous_system_state(self, cpu_id):
"""Read the FW previous system state.
Args:
cpu_id (:class:`~hailo_platform.drivers.hailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
return self._controller.previous_system_state(cpu_id)
def get_chip_temperature(self):
"""Returns the latest temperature measurements from the 2 internal temperature sensors of the Hailo chip.
Returns:
:class:`~hailo_platform.drivers.hailort.pyhailort.TemperatureInfo`:
Temperature in celsius of the 2 internal temperature sensors (TS), and a sample
count (a running 16-bit counter)
"""
return self._controller.get_chip_temperature()
def get_extended_device_information(self):
return self._controller.get_extended_device_information()
def _get_health_information(self):
return self._controller._get_health_information()
def set_pause_frames(self, rx_pause_frames_enable):
"""Enable/Disable Pause frames.
Args:
rx_pause_frames_enable (bool): False for disable, True for enable.
"""
self._controller.set_pause_frames(rx_pause_frames_enable)
def test_chip_memories(self):
"""test all chip memories using smart BIST
"""
self._controller.test_chip_memories()
def _get_device_handle(self):
return self._controller._get_device_handle()
class UdpHcpControl(HcpControl):
"""Control object that uses a HCP over UDP controller interface."""
def __init__(self, remote_ip, device=None, remote_control_port=22401, retries=2, response_timeout_seconds=10.0, ignore_socket_errors=False):
"""Initializes a new UdpControllerControl object.
Args:
remote_ip (str): The IPv4 address of the remote Hailo device (X.X.X.X).
remote_control_port (int, optional): The port that the remote Hailo device listens on.
response_timeout_seconds (float, optional): Number of seconds to wait until a response is received.
ignore_socket_errors (bool, optional): Ignore socket error (might be usefull for debugging).
"""
super(UdpHcpControl, self).__init__()
# In the C API we define the total amount of attempts, instead of the amount of retries.
max_number_of_attempts = retries + 1
self._controller = Control(Control.Type.ETH, remote_ip, remote_control_port, response_timeout_seconds=response_timeout_seconds, max_number_of_attempts=max_number_of_attempts)
self.set_udp_device(device)
self._device_id = self.identify()
def set_udp_device(self, device):
self._controller.set_device(device)
class PcieHcpControl(HcpControl):
"""Control object that uses a HCP over PCIe controller interface."""
def __init__(self, device=None, device_info=None):
"""Initializes a new HailoPcieController object."""
super(PcieHcpControl, self).__init__()
if device_info is None:
device_info = InternalPcieDevice.scan_devices()[0]
self._controller = Control(Control.Type.PCIE, None, None, pcie_device_info=device_info)
self.set_pcie_device(device)
self._device_id = self.identify()
def release(self):
if self._controller is None:
return
self._controller.release()
self._controller = None
def set_pcie_device(self, pcie_device):
"""Prepare the pcie device to be used after creating it."""
self._controller.set_device(pcie_device)
def set_notification_callback(self, callback_func, notification_id, opaque):
"""Set a callback function to be called when a notification is received.
Args:
callback_func (function): Callback function with the parameters (device, notification, opaque).
Note that throwing exceptions is not supported and will cause the program to terminate with an error!
notification_id (NotificationId): Notification ID to register the callback to.
opauqe (object): User defined data.
Note:
The notifications thread is started and closed in the use_device() context, so
notifications can only be received there.
"""
return self._controller.set_notification_callback(callback_func, notification_id, opaque)
def remove_notification_callback(self, notification_id):
"""Remove a notification callback which was already set.
Args:
notification_id (NotificationId): Notification ID to remove the callback from.
"""
return self._controller.remove_notification_callback(notification_id)
from hailo_platform.pyhailort.control_object import * # noqa F401

View File

@@ -1,66 +1 @@
#!/usr/bin/env python
from builtins import str
import netifaces as ni
from netaddr import IPAddress, IPNetwork
# As defined in sockios.h
SIOCGIFTXQLEN = 0x8942
# Interface name is 16 bytes (including NULL)
SIOCGIFTXQLEN_FMT = "16sI"
class NoInterfaceError(Exception):
"""Raised by get_interface_from_ip when no matching interface was found"""
pass
def get_interface_from_ip(ip_address):
"""Returns the interface name associated with the given ip addressself.
Args:
ip_address (str): the IP address to query.
Returns:
str: The name of the interface matching the given IP address.
"""
skipped_ifaces = []
for interface in ni.interfaces():
if ni.AF_INET not in ni.ifaddresses(interface):
skipped_ifaces.append(interface)
continue
af_inet_values = ni.ifaddresses(interface)[ni.AF_INET][0]
ip_addr, netmask = af_inet_values['addr'], af_inet_values['netmask']
if is_ip_in_network(ip_addr, netmask, ip_address):
return str(interface)
raise NoInterfaceError('No interface for {} found among {}'.format(ip_address, skipped_ifaces))
def get_interface_address(interface_name):
"""Returns the interface address associated with the given interface name.
Args:
interface_name (str): the name of the interface to query.
Returns:
str: The IP address of the interface matching the given interface_name.
"""
af_inet_values = ni.ifaddresses(interface_name)[ni.AF_INET][0]
return af_inet_values['addr']
def is_ip_in_network(network_ip, netmask, ip_in_question):
"""Checks whether an IP address is located in a given network.
Args:
network_ip (str): the IP address of the network interface.
netmask (str): the netmask of the given networkself.
ip_in_question (str): the IP address to compare against the network.
Returns:
bool: whether the IP address belongs to the given network.
"""
netmask_bits = IPAddress(netmask).netmask_bits()
return IPAddress(ip_in_question) in IPNetwork('{}/{}'.format(network_ip, netmask_bits))
from hailo_platform.pyhailort.ethernet_utils import * # noqa F401

View File

@@ -1,331 +1,2 @@
#!/usr/bin/env python
"""
.. module:: hailo_control_protocol
:synopsis: Implements a Hailo Control Protocol message.
"""
from builtins import object
from enum import Enum, IntEnum
import struct
# Supported protocol and Firmware version of current SDK.
SUPPORTED_PROTOCOL_VERSION = 2
SUPPORTED_FW_MAJOR = 4
SUPPORTED_FW_MINOR = 6
SUPPORTED_FW_REVISION = 0
MEGA_MULTIPLIER = 1000.0 * 1000.0
class HailoControlProtocolException(Exception):
pass
class DeviceArchitectureTypes(IntEnum):
HAILO8_A0 = 0
HAILO8_B0 = 1
MERCURY_CA = 2
def __str__(self):
return self.name
class BoardInformation(object):
def __init__(self, protocol_version, fw_version_major, fw_version_minor, fw_version_revision,
logger_version, board_name, is_release, device_architecture, serial_number, part_number, product_name):
self.protocol_version = protocol_version
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.APP)
self.logger_version = logger_version
self.board_name = board_name
self.is_release = is_release
self.device_architecture = DeviceArchitectureTypes(device_architecture)
self.serial_number = serial_number
self.part_number = part_number
self.product_name = product_name
def _string_field_str(self, string_field):
# Return <Not Configured> if the string field is empty
return string_field.rstrip('\x00') or "<Not Configured>"
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Control Protocol Version: {}\n' \
'Firmware Version: {}\n' \
'Logger Version: {}\n' \
'Board Name: {}\n' \
'Device Architecture: {}\n' \
'Serial Number: {}\n' \
'Part Number: {}\n' \
'Product Name: {}\n'.format(
self.protocol_version,
self.firmware_version,
self.logger_version,
self.board_name.rstrip('\x00'),
str(self.device_architecture),
self._string_field_str(self.serial_number),
self._string_field_str(self.part_number),
self._string_field_str(self.product_name))
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
@staticmethod
def get_hw_arch_str(device_arch):
if device_arch == DeviceArchitectureTypes.HAILO8_B0:
return 'hailo8'
elif device_arch == DeviceArchitectureTypes.MERCURY_CA:
return 'mercury'
else:
raise HailoControlProtocolException("Unsupported device architecture.")
class CoreInformation(object):
def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release):
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.CORE)
self.is_release = is_release
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Core Firmware Version: {}'.format(
self.firmware_version)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class TemperatureThrottlingLevel(object):
def __init__(self, level_number, temperature_threshold, hysteresis_temperature_threshold, throttling_nn_clock_freq):
self.level_number = level_number
self.temperature_threshold = temperature_threshold
self.hysteresis_temperature_threshold = hysteresis_temperature_threshold
self.throttling_nn_clock_freq = throttling_nn_clock_freq
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Temperature Throttling Level {}: \n' \
'Temperature Threshold: {}\n' \
'Hysteresis Temperature Threshold: {}\n' \
'Throttling NN Clock Frequency: {}\n' \
.format(self.level_number, self.temperature_threshold, self.hysteresis_temperature_threshold, self.throttling_nn_clock_freq)
def __repr__(self):
return self.__str__()
class HealthInformation(object):
def __init__(self, overcurrent_protection_active, current_overcurrent_zone, red_overcurrent_threshold, orange_overcurrent_threshold,
temperature_throttling_active, current_temperature_zone, current_temperature_throttling_level,
temperature_throttling_levels, orange_temperature_threshold, orange_hysteresis_temperature_threshold,
red_temperature_threshold, red_hysteresis_temperature_threshold):
self.overcurrent_protection_active = overcurrent_protection_active
self.current_overcurrent_zone = current_overcurrent_zone
self.red_overcurrent_threshold = red_overcurrent_threshold
self.orange_overcurrent_threshold = orange_overcurrent_threshold
self.temperature_throttling_active = temperature_throttling_active
self.current_temperature_zone = current_temperature_zone
self.current_temperature_throttling_level = current_temperature_throttling_level
self.orange_temperature_threshold = orange_temperature_threshold
self.orange_hysteresis_temperature_threshold = orange_hysteresis_temperature_threshold
self.red_temperature_threshold = red_temperature_threshold
self.red_hysteresis_temperature_threshold = red_hysteresis_temperature_threshold
# Add TemperatureThrottlingLevel in case it has new throttling_nn_clock_freq. level_number can be used as only last
# levels can be with the same freq
self.temperature_throttling_levels = []
if self.temperature_throttling_active:
throttling_nn_clock_frequencies = []
for level_number, temperature_throttling_level in enumerate(temperature_throttling_levels):
if temperature_throttling_level.throttling_nn_clock_freq not in throttling_nn_clock_frequencies:
throttling_nn_clock_frequencies.append(temperature_throttling_level.throttling_nn_clock_freq)
self.temperature_throttling_levels.append(TemperatureThrottlingLevel(level_number,
temperature_throttling_level.temperature_threshold,
temperature_throttling_level.hysteresis_temperature_threshold,
temperature_throttling_level.throttling_nn_clock_freq))
def __repr__(self):
return self.__str__()
def __str__(self):
"""Returns:
str: Human readable string.
"""
temperature_throttling_levels_str = "\n".join(["\n\n{}\n".format(str(temperature_throttling_level)) for temperature_throttling_level in self.temperature_throttling_levels]) \
if self.temperature_throttling_active else "<Temperature throttling is disabled>"
return 'Overcurrent Protection Active: {}\n' \
'Overcurrent Protection Current Overcurrent Zone: {}\n' \
'Overcurrent Protection Red Threshold: {}\n' \
'Overcurrent Protection Orange Threshold: {}\n' \
'Temperature Protection Red Threshold: {}\n' \
'Temperature Protection Red Hysteresis Threshold: {}\n' \
'Temperature Protection Orange Threshold: {}\n' \
'Temperature Protection Orange Hysteresis Threshold: {}\n' \
'Temperature Protection Throttling State: {}\n' \
'Temperature Protection Current Zone: {}\n' \
'Temperature Protection Current Throttling Level: {}\n' \
'Temperature Protection Throttling Levels: {}' \
.format(self.overcurrent_protection_active, self.current_overcurrent_zone, self.red_overcurrent_threshold,
self.orange_overcurrent_threshold, self.red_temperature_threshold,
self.red_hysteresis_temperature_threshold, self.orange_temperature_threshold,
self.orange_hysteresis_temperature_threshold, self.temperature_throttling_active,
self.current_temperature_zone, self.current_temperature_throttling_level, temperature_throttling_levels_str)
class ExtendedDeviceInformation(object):
def __init__(self, neural_network_core_clock_rate, supported_features, boot_source, lcs, soc_id, eth_mac_address, unit_level_tracking_id, soc_pm_values):
self.neural_network_core_clock_rate = neural_network_core_clock_rate
self.supported_features = SupportedFeatures(supported_features)
self.boot_source = boot_source
self.lcs = lcs
self.soc_id = soc_id
self.eth_mac_address = eth_mac_address
self.unit_level_tracking_id = unit_level_tracking_id
self.soc_pm_values = soc_pm_values
def __str__(self):
"""Returns:
str: Human readable string.
"""
string = 'Neural Network Core Clock Rate: {}MHz\n' \
'{}' \
'Boot source: {}\n' \
'LCS: {}\n'.format(
self.neural_network_core_clock_rate / MEGA_MULTIPLIER,
str(self.supported_features),
str(self.boot_source.name),
str(self.lcs))
if any(self.soc_id):
string += 'SoC ID: ' + (self.soc_id.hex())
if any(self.eth_mac_address):
string += '\nMAC Address: ' + (":".join("{:02X}".format(i) for i in self.eth_mac_address))
if any(self.unit_level_tracking_id):
string += '\nULT ID: ' + (self.unit_level_tracking_id.hex())
if any(self.soc_pm_values):
string += '\nPM Values: ' + (self.soc_pm_values.hex())
return string
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class HailoFirmwareMode(Enum):
"""Indication that firmware version is stable and official """
DEVELOP = 'develop'
RELEASE = 'release'
class HailoFirmwareType(Enum):
"""Indication the firmware type """
CORE = 'core'
APP = 'app'
class HailoResetTypes(Enum):
"""Defines the available reset types."""
CHIP = 'chip'
NN_CORE = 'nn_core'
SOFT = 'soft'
FORCED_SOFT = 'forced_soft'
class HailoFirmwareVersion(object):
"""Represents a Hailo chip firmware version."""
DEV_BIT = 0x80000000
CORE_BIT = 0x08000000
FW_VERSION_FORMAT = '<III'
def __init__(self, firmware_version_buffer, is_release, fw_type):
"""Initialize a new Hailo Firmware Version object.
Args:
firmware_version_buffer (str): A buffer containing the firmware version struct.
is_release (bool, optional): Flag indicating if firmware is at develop/release mode.
None indicates unknown
"""
self.major, self.minor, self.revision = struct.unpack(
self.FW_VERSION_FORMAT,
firmware_version_buffer)
self.fw_type = fw_type
self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
self.revision &= ~(self.CORE_BIT | self.DEV_BIT)
def __str__(self):
"""Returns:
str: Firmware version in a human readable format.
"""
return '{}.{}.{} ({},{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value)
@classmethod
def construct_from_params(cls, major, minor, revision, is_release, fw_type):
"""Returns:
class HailoFirmwareVersion : with the given Firmware version.
"""
return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release, fw_type)
@property
def comparable_value(self):
"""A value that could be compared to other firmware versions."""
return (self.major << 64) + (self.minor << 32) + (self.revision)
def __hash__(self):
return self.comparable_value
def __eq__(self, other):
return self.comparable_value == other.comparable_value
# TODO: Required for Python2 BW compatibility (SDK-10038)
# This impl' comes by default in Python3
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self.comparable_value < other.comparable_value
def check_protocol_compatibility(self, other):
return ((self.major == other.major) and (self.minor == other.minor))
class SupportedFeatures(object):
def __init__(self, supported_features):
self.ethernet = supported_features.ethernet
self.mipi = supported_features.mipi
self.pcie = supported_features.pcie
self.current_monitoring = supported_features.current_monitoring
self.mdio = supported_features.mdio
def _feature_str(self, feature_name, is_feature_enabled):
return '{}: {}\n'.format(feature_name, 'Enabled' if is_feature_enabled else 'Disabled')
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Device supported features: \n' + \
self._feature_str('Ethernet', self.ethernet) + \
self._feature_str('MIPI', self.mipi) + \
self._feature_str('PCIE', self.pcie) + \
self._feature_str('Current Monitoring', self.current_monitoring) + \
self._feature_str('MDIO', self.mdio)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
def _is_feature_enabled(self, feature):
return (self.supported_features & feature) != 0
from hailo_platform.pyhailort.hailo_control_protocol import * # noqa F401

View File

@@ -1,191 +1,2 @@
#!/usr/bin/env python
from builtins import object
import struct
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.drivers.hailort.pyhailort import Endianness
logger = default_logger()
#: Variable which defines that the I2C slave is not behind a switch.
NO_I2C_SWITCH = 5
class I2CSlavesException(Exception):
pass
class I2CSlave(object):
def __init__(self, name, bus_index, slave_address, switch_number=NO_I2C_SWITCH,
register_address_size=1, endianness=Endianness.LITTLE_ENDIAN,
should_hold_bus=False):
"""Initialize a class which describes an I2C slave.
Args:
name (str): The name of the I2C slave.
bus_index (int): The bus number the I2C slave is connected to.
slave_address (int): The address of the I2C slave.
switch_number (int): The number of the switch the i2c salve is connected to.
register_address_size (int): Slave register address length (in bytes).
endianness (:class:`~hailo_platform.drivers.hailort.pyhailort.Endianness`): The endianness of the slave.
should_hold_bus (bool): Should hold the bus during the read.
"""
self._name = name
self._bus_index = bus_index
self._slave_address = slave_address
self._switch_number = switch_number
self._register_address_size = register_address_size
self._endianness = endianness
self._should_hold_bus = should_hold_bus
def __repr__(self):
# Returning '' for the sphinx doc
return ''
@property
def name(self):
"""Get the name of the I2C slave.
Returns:
str: Name of the I2C slave.
"""
return self._name
@property
def bus_index(self):
"""Get bus index the I2C slave is connected to.
Returns:
int: Index of the bus the I2C slave is connected to.
"""
return self._bus_index
@property
def slave_address(self):
"""Get the address of the salve.
Returns:
int: The address of the I2C slave.
"""
return self._slave_address
@property
def register_address_size(self):
"""Get the slave register address length (in bytes). This number represents how many bytes are in the
register address the slave can access.
Returns:
int: Slave register address length.
Note:
Pay attention to the slave endianness (:class:`~hailo_platform.drivers.hailort.pyhailort.Endianness`).
"""
return self._register_address_size
@property
def switch_number(self):
"""Get the switch number the slave is connected to.
Returns:
int: The number of the switch the I2C is behind.
Note:
If :data:`NO_I2C_SWITCH` is returned, it means the slave is not behind a switch.
"""
return self._switch_number
@property
def endianness(self):
"""Get the slave endianness.
Returns:
:class:`~hailo_platform.drivers.hailort.pyhailort.Endianness`: The slave endianness.
"""
return self._endianness
@property
def should_hold_bus(self):
"""Returns a Boolean indicating if the bus will be held while reading from the slave.
Returns:
bool: True if the bus would be held, otherwise False.
"""
return self._should_hold_bus
# DVM's
#: Class which represents the MIPI AVDD I2C slave.
I2C_SLAVE_MIPI_AVDD = I2CSlave("DVM_MIPI_AVDD", 0, 0x40)
#: Class which represents the USB AVDD IO slave.
I2C_SLAVE_USB_AVDD_IO = I2CSlave("DVM_USB_AVDD_IO", 0, 0x41)
#: Class which represents the V_CORE slave.
I2C_SLAVE_VDD_CORE = I2CSlave("DVM_VDD_CORE", 0, 0x42)
#: Class which represents the VDD TOP slave.
I2C_SLAVE_VDD_TOP = I2CSlave("DVM_VDD_TOP", 0, 0x43)
#: Class which represents the MIPI AVDD_H I2C slave.
I2C_SLAVE_MIPI_AVDD_H = I2CSlave("DVM_MIPI_AVDD_H", 0, 0x44)
#: Class which represents the DVM USB AVDD IO HV slave.
I2C_SLAVE_USB_AVDD_IO_HV = I2CSlave("DVM_USB_AVDD_IO_HV", 0, 0x45)
#: Class which represents the DVM_VDDIO slave.
I2C_SLAVE_VDD_IO = I2CSlave("DVM_VDD_IO", 0, 0x46)
#: Class which represents the DVM_AVDD_H slave.
I2C_SLAVE_AVDD_H = I2CSlave("DVM_AVDD_H", 0, 0x47)
#: Class which represents the DVM_SDIO_VDDIO slave.
I2C_SLAVE_SDIO_VDD_IO = I2CSlave("DVM_SDIO_VDD_IO", 0, 0x4d)
#: Class which represents the DVM_SDIO_VDDIO slave.
I2C_SLAVE_M_DOT_2_OVERCURREN_PROTECTION = I2CSlave("M_DOT_2_OVERCURREN_PROTECTION", 0, 0x40)
#: Class which represents the I2S codec I2C slave.
I2C_SLAVE_I2S_CODEC = I2CSlave("I2S_codec", 1, 0x18, should_hold_bus=True)
#: Class which represents the I2C to gpio I2C slave.
I2C_SLAVE_I2C_TO_GPIO = I2CSlave("I2C_to_GPIO", 0, 0x22)
#: Class which represents the I2C switch slave.
I2C_SLAVE_SWITCH = I2CSlave("I2C_SWITCH", 1, 0x70)
#: Class which represents the I2C TEMP_sensor_0 slave.
I2C_SLAVE_TEMP_SENSOR_0 = I2CSlave("TEMP_sensor_0", 0, 0x29)
#: Class which represents the I2S TEMP_sensor_1 slave.
I2C_SLAVE_TEMP_SENSOR_1 = I2CSlave("TEMP_sensor_1", 0, 0x2A)
#: Class which represents the EEPROM I2C slave.
I2C_SLAVE_EEPROM = I2CSlave("EEPROM", 0, 0x50, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
# External hardware
#: Class which represents the raspicam I2C slave.
I2C_SLAVE_RASPICAM = I2CSlave("RaspiCam", 1, 0x36, switch_number=1, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
I2C_SLAVE_ONSEMI_CAMERA_AR0220 = I2CSlave('Onsemi', 1, 0x10, switch_number=0, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
I2C_SLAVE_ONSEMI_CAMERA_AS0149 = I2CSlave('Onsemi', 1, (0x90 >> 1), switch_number=0, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
def set_i2c_switch(control_object, slave, slave_switch=None):
"""Set the I2C switch in order to perform actions from the I2C slave.
Args:
control_object (:class:`~hailo_platform.drivers.control_object.HcpControl`): Control object
which communicates with the Hailo chip.
slave (:class:`I2CSlave`): Slave which the switch is set for.
slave_switch (:class:`I2CSlave`): The I2C slave for the switch it self. Defaults to
:data:`I2C_SLAVE_SWITCH`.
"""
I2C_SWITCH_REGISTER_SIZE = 1
if NO_I2C_SWITCH != slave.switch_number:
if not slave_switch:
slave_switch = I2C_SLAVE_SWITCH
# Set the switch value that should be written
switch_value = 1 << slave.switch_number
# Write new value to the switch
control_object.i2c_write(slave_switch, switch_value, struct.pack('b', switch_value))
# Read data from the switch, make sure write was successful
read_data, = struct.unpack('b', control_object.i2c_read(slave_switch, switch_value, I2C_SWITCH_REGISTER_SIZE))
if read_data != switch_value:
raise I2CSlavesException("Switch writing has failed. Read data is different then expected %s != %s" % (
read_data,
switch_value))
from hailo_platform.pyhailort.i2c_slaves import * # noqa F401

View File

@@ -1,11 +1 @@
from hailo_platform.drivers.hailort.pyhailort import (DvmTypes, PowerMeasurementTypes, # noqa F401
SamplingPeriod, AveragingFactor,
HailoPowerMeasurementUtils)
""" Amount of time between each power measurement interval.
The default values for provides by the sensor a new value every:
2 * sampling_period (1.1) * averaging_factor (256) [ms].
Therefore we want it to be the period of time that the core will sleep between samples,
plus a factor of 20 percent """
DEFAULT_POWER_MEASUREMENT_DELAY_PERIOD_MS = int((HailoPowerMeasurementUtils.return_real_sampling_period(SamplingPeriod.PERIOD_1100us) / 1000.0 *
HailoPowerMeasurementUtils.return_real_averaging_factor(AveragingFactor.AVERAGE_256) * 2) * 1.2)
from hailo_platform.pyhailort.power_measurement import * # noqa F401

View File

@@ -1,465 +1 @@
#!/usr/bin/env python
"""Hailo hardware API"""
from __future__ import division
import gc
import os
from contextlib import contextmanager
from hailo_platform.drivers.control_object import UdpHcpControl, PcieHcpControl
from hailo_platform.common.compatibility import ensure_str
from hailo_platform.common.targets.inference_targets import InferenceTargets, InferenceObject, InferenceTargetException
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.drivers.hailo_controller.hailo_control_protocol import BoardInformation
from hailo_platform.drivers.hailort.pyhailort import ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice, HailoRTTransformUtils, HailoUdpScan, HailoRTException
class HailoHWObjectException(InferenceTargetException):
"""Raised in any error related to Hailo hardware."""
pass
class HailoHWObject(InferenceObject):
"""Abstract Hailo hardware device representation."""
IS_NUMERIC = True
def __init__(self):
"""Create the Hailo hardware object."""
super(HailoHWObject, self).__init__()
self._last_interact_time = None
self._total_time = None
self._id = None
self._hw_arch = None
self._logger = default_logger()
self._debug = False
self._is_device_used = False
self._hef_loaded = False
@property
def device_id(self):
"""Getter for the device_id.
Returns:
str: A string ID of the device. BDF for PCIe devices, MAC address for Ethernet devices, "Core" for core devices.
"""
return self._id
@property
def sorted_output_layer_names(self):
"""Getter for the property sorted_output_names.
Returns:
list of str: Sorted list of the output layer names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to sorted_output_layer_names is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_sorted_output_names()
@contextmanager
def use_device(self, *args, **kwargs):
"""A context manager that wraps the usage of the device (deprecated)."""
self._is_device_used = True
yield
self._is_device_used = False
def get_output_device_layer_to_original_layer_map(self):
"""Get a mapping between the device outputs to the layers' names they represent.
Returns:
dict: Keys are device output names and values are lists of layers' names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {stream_info.name : self._loaded_network_groups[0].get_vstream_names_from_stream_name(stream_info.name)
for stream_info in self.get_output_stream_infos()}
def get_original_layer_to_device_layer_map(self):
"""Get a mapping between the layer names and the device outputs that contain them.
Returns:
dict: Keys are the names of the layers and values are device outputs names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {vstream_info.name : self._loaded_network_groups[0].get_stream_names_from_vstream_name(vstream_info.name)
for vstream_info in self.get_output_vstream_infos()}
@property
def device_input_layers(self):
"""Get a list of the names of the device's inputs."""
return [layer.name for layer in self.get_input_stream_infos()]
@property
def device_output_layers(self):
"""Get a list of the names of the device's outputs."""
return [layer.name for layer in self.get_output_stream_infos()]
def hef_loaded(self):
"""Return True if this object has loaded the model HEF to the hardware device."""
return self._hef_loaded
def outputs_count(self):
"""Return the amount of output tensors that are returned from the hardware device for every
input image.
"""
return len(self.get_output_vstream_infos())
def _clear_shapes(self):
self._hw_consts = None
@property
def model_name(self):
"""Get the name of the current model.
Returns:
str: Model name.
"""
if len(self._loaded_network_groups) == 1:
return self._loaded_network_groups[0].name
raise HailoHWObjectException(
"This function is only supported when there is exactly 1 loaded network group. one should use HEF.get_network_group_names() / ConfiguredNetwork.name / ActivatedNetwork.name")
def get_output_shapes(self):
"""Get the model output shapes, as returned to the user (without any hardware padding).
Returns:
Tuple of output shapes, sorted by the output names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Calling get_output_shapes is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_shapes()
class HailoChipObject(HailoHWObject):
"""Hailo hardware device representation"""
IS_NUMERIC = True
IS_HARDWARE = True
def __init__(self):
"""Create the Hailo Chip hardware object."""
super(HailoChipObject, self).__init__()
self._id = "Generic Hailo Device"
self._control_object = None
self._loaded_network_groups = []
self._creation_pid = os.getpid()
@property
def control(self):
""":class:`HailoControl <hailo_platform.drivers.control_object.HailoControl>`: Returns
the control object of this device, which implements the control API of the Hailo device.
.. attention:: Use the low level control API with care.
"""
return self._control_object
def get_all_input_layers_dtype(self):
"""Get the model inputs dtype.
Returns:
dict of :obj:'numpy.dtype': where the key is model input_layer name, and the value is dtype as the device expect to get for this input.
"""
return {stream.name: HailoRTTransformUtils.get_dtype(stream.data_bytes) for stream in self.get_input_stream_infos()}
def get_input_vstream_infos(self, network_name=None):
"""Get input vstreams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_vstream_infos(network_name=network_name)
def get_output_vstream_infos(self, network_name=None):
"""Get output vstreams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_vstream_infos(network_name=network_name)
def get_all_vstream_infos(self, network_name=None):
"""Get input and output vstreams information.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_vstream_infos(network_name=network_name)
def get_input_stream_infos(self, network_name=None):
"""Get the input low-level streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with information objects
of all input low-level streams.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_stream_infos(network_name=network_name)
def get_output_stream_infos(self, network_name=None):
"""Get the output low-level streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.VStreamInfo`: with information objects
of all output low-level streams.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_stream_infos(network_name=network_name)
def get_all_stream_infos(self, network_name=None):
"""Get input and output streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.drivers.hailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_stream_infos(network_name=network_name)
@property
def loaded_network_groups(self):
"""Getter for the property _loaded_network_groups.
Returns:
list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
"""
return self._loaded_network_groups
@property
def _loaded_network_group(self):
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network layer info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0]
def configure(self, hef, configure_params_by_name={}):
"""Configures target device from HEF object.
Args:
hef (:class:`~hailo_platform.drivers.hailort.pyhailort.HEF`): HEF to configure the device from
configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
"""
if self._creation_pid != os.getpid():
raise HailoRTException("Device can only be configured from the process it was created in.")
configured_apps = self._control_object.configure(hef, configure_params_by_name)
self._hef_loaded = True
configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
self._loaded_network_groups.extend(configured_networks)
return configured_networks
def get_input_shape(self, name=None):
"""Get the input shape (not padded) of a network.
Args:
name (str, optional): The name of the desired input. If a name is not provided, return
the first input_dataflow shape.
Returns:
Tuple of integers representing the input_shape.
"""
if name is None:
name = self.get_input_vstream_infos()[0].name
for input_vstream in self.get_input_vstream_infos():
if input_vstream.name == name:
return input_vstream.shape
raise HailoHWObjectException("There is no input named {}! the input names are: {}".format(name,
[input_vstream.name for input_vstream in self.get_input_vstream_infos()]))
def get_index_from_name(self, name):
"""Get the index in the output list from the name.
Args:
name (str): The name of the output.
Returns:
int: The index of the layer name in the output list.
"""
try:
return self.sorted_output_layer_names.index(ensure_str(name))
except ValueError:
if len(self.sorted_output_layer_names) == 1:
# Case regard to SDK-9366 - see Jira for details.
self._logger.warning('Incorrect meta item - layer defuse_name does not match layer name.')
return 0
else:
raise HailoHWObjectException("Could not get index for outputs properly.")
class EthernetDevice(HailoChipObject):
"""Represents any Hailo hardware device that supports UDP control and dataflow."""
NAME = InferenceTargets.UDP_CONTROLLER
def __init__(
self,
remote_ip,
remote_control_port=22401):
"""Create the Hailo UDP hardware object.
Args:
remote_ip (str): Device IP address.
remote_control_port (int, optional): UDP port to which the device listens for control.
Defaults to 22401.
"""
super(EthernetDevice, self).__init__()
self._remote_ip = remote_ip
gc.collect()
self._remote_control_port = remote_control_port
# EthernetDevice __del__ function tries to release self._eth_device.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
self._eth_device = None
self._id = "{}".format(self._remote_ip)
if not self.hef_loaded():
self._open_device()
identity = self._control_object._device_id
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod
def scan_devices(interface_name, timeout_seconds=3):
"""Scans for all eth devices on a specific network interface.
Args:
interface_name (str): Interface to scan.
timeout_seconds (int, optional): timeout for scan operation. Defaults to 3.
Returns:
list of str: IPs of scanned devices.
"""
udp_scanner = HailoUdpScan()
return udp_scanner.scan_devices(interface_name, timeout_seconds=timeout_seconds)
def _open_device(self):
self._eth_device = InternalEthernetDevice(self._remote_ip, self._remote_control_port)
self._control_object = UdpHcpControl(self._remote_ip, device=self._eth_device, remote_control_port=self._remote_control_port)
def _close(self):
if self._eth_device is not None:
self._eth_device.release()
self._eth_device = None
def __enter__(self):
if not self.hef_loaded:
return None
self._open_device()
return self
def __exit__(self, *args):
self._close()
return False
def __del__(self):
self._close()
@property
def remote_ip(self):
"""Return the IP of the remote device."""
return self._remote_ip
class PcieDevice(HailoChipObject):
"""Hailo PCIe production device representation."""
NAME = InferenceTargets.PCIE_CONTROLLER
def __init__(
self,
device_info=None):
"""Create the Hailo PCIe hardware object.
Args:
device_info (:obj:`hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`, optional): Device info to create, call
:func:`PcieDevice.scan_devices` to get list of all available devices.
"""
super(PcieDevice, self).__init__()
gc.collect()
# PcieDevice __del__ function tries to release self._pcie_device.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
self._pcie_device = None
self._device_info = device_info
if not self.hef_loaded():
self._open_device()
# At this point self._device_info is already initialized
self._id = "{}".format(self._device_info)
identity = self._control_object._device_id
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod
def scan_devices():
"""Scans for all pcie devices on the system.
Returns:
list of :obj:`hailo_platform.drivers.hailort.pyhailort.PcieDeviceInfo`
"""
return InternalPcieDevice.scan_devices()
def _open_device(self):
self._pcie_device = InternalPcieDevice(self._device_info)
self._device_info = self._pcie_device._device_info
self._control_object = PcieHcpControl(device=self._pcie_device, device_info=self._device_info)
def _close(self):
if self._pcie_device is not None:
self._pcie_device.release()
self._pcie_device = None
def __enter__(self):
if not self.hef_loaded:
return None
self._open_device()
return self
def __exit__(self, *args):
self._close()
return False
def __del__(self):
self._close()
from hailo_platform.pyhailort.hw_object import * # noqa F401

View File

@@ -1,10 +0,0 @@
#!/usr/bin/env python
import hailo_platform
from hailo_platform.common.paths_manager.paths import SDKPaths, Singleton
import os
from future.utils import with_metaclass
class PlatformPaths(with_metaclass(Singleton, SDKPaths)):
def join_platform(self, path):
return os.path.join(os.path.abspath(hailo_platform.__path__[0]), path)

View File

@@ -0,0 +1,745 @@
#!/usr/bin/env python
"""Control operations for the Hailo hardware device."""
import struct
import sys
import signal
from builtins import object
from abc import ABCMeta, abstractmethod
from future.utils import with_metaclass
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.pyhailort.hailo_control_protocol import BoardInformation, CoreInformation, DeviceArchitectureTypes, ExtendedDeviceInformation, HealthInformation
from hailo_platform.pyhailort.power_measurement import SamplingPeriod, AveragingFactor, DvmTypes, PowerMeasurementTypes, MeasurementBufferIndex, _get_buffer_index_enum_member
from hailo_platform.pyhailort.pyhailort import InternalPcieDevice, ExceptionWrapper
import hailo_platform.pyhailort._pyhailort as _pyhailort
class ControlObjectException(Exception):
"""Raised on illegal ContolObject operation."""
pass
class FirmwareUpdateException(Exception):
pass
class HailoControl(with_metaclass(ABCMeta, object)):
"""Control object that sends control operations to a Hailo hardware device."""
def __init__(self):
"""Initializes a new HailoControl object."""
self._logger = default_logger()
self._device = None
if sys.platform != "win32":
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGWINCH])
@abstractmethod
def open(self):
"""Initializes the resources needed for using a control device."""
pass
@abstractmethod
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def configure(self, hef, configure_params_by_name={}):
"""
Configures device from HEF object.
Args:
hef (:class:`~hailo_platform.pyhailort.pyhailort.HEF`): HEF to configure the
device from.
configure_params_by_name (dict, optional): Maps between each net_group_name to
configure_params. In case of a mismatch with net_groups_names, default params will
be used.
"""
with ExceptionWrapper():
return self._device.configure(hef._hef, configure_params_by_name)
@abstractmethod
def chip_reset(self):
"""Resets the device (chip reset)."""
pass
@abstractmethod
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte.
"""
pass
@abstractmethod
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip.
Byte order isn't changed. The core uses little-endian byte order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
pass
class HcpControl(HailoControl):
"""Control object that uses the HCP protocol for controlling the device."""
WORD_SIZE = 4
def __init__(self):
super(HcpControl, self).__init__()
@property
def device_id(self):
"""Getter for the device_id.
Returns:
str: A string ID of the device. BDF for PCIe devices, IP address for Ethernet devices, "Core" for core devices.
"""
return self._device_id
def open(self):
"""Initializes the resources needed for using a control device."""
pass
def close(self):
"""Releases the resources that were allocated for the control device."""
pass
def chip_reset(self):
"""Resets the device (chip reset)."""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.CHIP)
def nn_core_reset(self):
"""Resets the nn_core."""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.NN_CORE)
def soft_reset(self):
"""reloads the device firmware (soft reset)"""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.SOFT)
def forced_soft_reset(self):
"""reloads the device firmware (forced soft reset)"""
with ExceptionWrapper():
return self._device.reset(_pyhailort.ResetDeviceMode.FORCED_SOFT)
def read_memory(self, address, data_length):
"""Reads memory from the Hailo chip. Byte order isn't changed. The core uses little-endian
byte order.
Args:
address (int): Physical address to read from.
data_length (int): Size to read in bytes.
Returns:
list of str: Memory read from the chip, each index in the list is a byte
"""
with ExceptionWrapper():
return self._device.read_memory(address, data_length)
def write_memory(self, address, data_buffer):
"""Write memory to Hailo chip. Byte order isn't changed. The core uses little-endian byte
order.
Args:
address (int): Physical address to write to.
data_buffer (list of str): Data to write.
"""
with ExceptionWrapper():
return self._device.write_memory(address, data_buffer, len(data_buffer))
def power_measurement(self, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Perform a single power measurement on an Hailo chip. It works with the default settings
where the sensor returns a new value every 2.2 ms without averaging the values.
Args:
dvm (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Returns:
float: The measured power. \n
For :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power. For all supported
measurement types, please look at
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
with ExceptionWrapper():
return self._device.power_measurement(dvm, measurement_type)
def start_power_measurement(self, delay=None, averaging_factor=AveragingFactor.AVERAGE_256, sampling_period=SamplingPeriod.PERIOD_1100us):
"""Start performing a long power measurement.
Args:
delay: Unused parameter. Will be removed in future versions.
averaging_factor (:class:`~hailo_platform.pyhailort.pyhailort.AveragingFactor`):
Number of samples per time period, sensor configuration value.
sampling_period (:class:`~hailo_platform.pyhailort.pyhailort.SamplingPeriod`):
Related conversion time, sensor configuration value. The sensor samples the power
every ``sampling_period`` [ms] and averages every ``averaging_factor`` samples. The
sensor provides a new value every: 2 * sampling_period * averaging_factor [ms]. The
firmware wakes up every ``delay`` [ms] and checks the sensor. If there is a new`
value to read from the sensor, the firmware reads it. Note that the average
calculated by the firmware is "average of averages", because it averages values
that have already been averaged by the sensor.
"""
# TODO: Remove deprecated arg
if delay is not None:
self._logger.warning("Passing 'delay' to 'start_power_measurement()' is deprecated and will be removed in future versions")
with ExceptionWrapper():
return self._device.start_power_measurement(averaging_factor, sampling_period)
def stop_power_measurement(self):
"""Stop performing a long power measurement. Deletes all saved results from the firmware.
Calling the function eliminates the start function settings for the averaging the samples,
and returns to the default values, so the sensor will return a new value every 2.2 ms
without averaging values.
"""
with ExceptionWrapper():
return self._device.stop_power_measurement()
def set_power_measurement(self, buffer_index=MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0, dvm=DvmTypes.AUTO, measurement_type=PowerMeasurementTypes.AUTO):
"""Set parameters for long power measurement on an Hailo chip.
Args:
buffer_index (:class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex`): Index of the buffer on the firmware the data would be saved at.
Default is :class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0`
dvm (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes`):
Which DVM will be measured. Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) will be different according to the board: \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for EVB is an approximation to the total power consumption of the chip in PCIe setups.
It sums :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.VDD_CORE`,
:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.MIPI_AVDD` and :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AVDD_H`.
Only :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER` can measured with this option. \n
Default (:class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.AUTO`) for platforms supporting current monitoring (such as M.2 and mPCIe): :class:`~hailo_platform.pyhailort.pyhailort.DvmTypes.OVERCURRENT_PROTECTION`
measurement_type
(:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`):
The type of the measurement.
Note:
This function can perform measurements for more than just power. For all supported measurement types
view :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`
"""
# TODO: Remove deprecated arg
if isinstance(buffer_index, int):
self._logger.warning("Passing integer as 'buffer_index' to 'set_power_measurement()' is deprecated. One should pass "
":class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex` as 'buffer_index' instead.")
buffer_index = _get_buffer_index_enum_member(buffer_index)
with ExceptionWrapper():
return self._device.set_power_measurement(buffer_index, dvm, measurement_type)
def get_power_measurement(self, buffer_index=MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0, should_clear=True):
"""Read measured power from a long power measurement
Args:
buffer_index (:class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex`): Index of the buffer on the firmware the data would be saved at.
Default is :class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0`
should_clear (bool): Flag indicating if the results saved at the firmware will be deleted after reading.
Returns:
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementData`:
Object containing measurement data \n
For :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`: \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.SHUNT_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.BUS_VOLTAGE`: Unit is mV. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.POWER`: Unit is W. \n
- :class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes.CURRENT`: Unit is mA. \n
Note:
This function can perform measurements for more than just power.
For all supported measurement types view
:class:`~hailo_platform.pyhailort.pyhailort.PowerMeasurementTypes`.
"""
if self.device_id.device_architecture != DeviceArchitectureTypes.HAILO8_B0:
raise ControlObjectException("Invalid device architecture: {}".format(self.device_id.device_architecture))
# TODO: Remove deprecated arg
if isinstance(buffer_index, int):
self._logger.warning("Passing integer as 'buffer_index' to 'get_power_measurement()' is deprecated. One should pass "
":class:`~hailo_platform.pyhailort.pyhailort.MeasurementBufferIndex` as 'buffer_index' instead.")
buffer_index = _get_buffer_index_enum_member(buffer_index)
with ExceptionWrapper():
return self._device.get_power_measurement(buffer_index, should_clear)
def _examine_user_config(self):
with ExceptionWrapper():
return self._device.examine_user_config()
def read_user_config(self):
"""Read the user configuration section as binary data.
Returns:
str: User config as a binary buffer.
"""
with ExceptionWrapper():
return self._device.read_user_config()
def write_user_config(self, configuration):
"""Write the user configuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
with ExceptionWrapper():
return self._device.write_user_config(configuration)
def _erase_user_config(self):
with ExceptionWrapper():
return self._device.erase_user_config()
def read_board_config(self):
"""Read the board configuration section as binary data.
Returns:
str: Board config as a binary buffer.
"""
with ExceptionWrapper():
return self._device.read_board_config()
def write_board_config(self, configuration):
"""Write the static confuration.
Args:
configuration (str): A binary representation of a Hailo device configuration.
"""
with ExceptionWrapper():
return self._device.write_board_config(configuration)
def identify(self):
"""Gets the Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
with ExceptionWrapper():
response = self._device.identify()
board_information = BoardInformation(response.protocol_version, response.fw_version.major,
response.fw_version.minor, response.fw_version.revision, response.logger_version,
response.board_name, response.is_release, int(response.device_architecture), response.serial_number,
response.part_number, response.product_name)
return board_information
def core_identify(self):
"""Gets the Core Hailo chip identification.
Returns:
class HailoIdentifyResponse with Protocol version.
"""
with ExceptionWrapper():
response = self._device.core_identify()
core_information = CoreInformation(response.fw_version.major, response.fw_version.minor,
response.fw_version.revision, response.is_release)
return core_information
def set_fw_logger(self, level, interface_mask):
"""Configure logger level and interface of sending.
Args:
level (FwLoggerLevel): The minimum logger level.
interface_mask (int): Output interfaces (mix of FwLoggerInterface).
"""
with ExceptionWrapper():
return self._device.set_fw_logger(level, interface_mask)
def set_throttling_state(self, should_activate):
"""Change throttling state of temperature protection component.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
with ExceptionWrapper():
return self._device.set_throttling_state(should_activate)
def get_throttling_state(self):
"""Get the current throttling state of temperature protection component.
Returns:
bool: true if temperature throttling is enabled, false otherwise.
"""
with ExceptionWrapper():
return self._device.get_throttling_state()
def _set_overcurrent_state(self, should_activate):
"""Control whether the overcurrent protection is enabled or disabled.
Args:
should_activate (bool): Should be true to enable or false to disable.
"""
with ExceptionWrapper():
return self._device._set_overcurrent_state(should_activate)
def _get_overcurrent_state(self):
"""Get the overcurrent protection state.
Returns:
bool: true if overcurrent protection is enabled, false otherwise.
"""
with ExceptionWrapper():
return self._device._get_overcurrent_state()
@staticmethod
def _create_c_i2c_slave(pythonic_slave):
c_slave = _pyhailort.I2CSlaveConfig()
c_slave.endianness = pythonic_slave.endianness
c_slave.slave_address = pythonic_slave.slave_address
c_slave.register_address_size = pythonic_slave.register_address_size
c_slave.bus_index = pythonic_slave.bus_index
return c_slave
def i2c_write(self, slave, register_address, data):
"""Write data to an I2C slave.
Args:
slave (:class:`hailo_platform.pyhailort.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register to which the data will be written.
data (str): The data that will be written.
"""
c_slave = HcpControl._create_c_i2c_slave(slave)
with ExceptionWrapper():
return self._device.i2c_write(c_slave, register_address, data, len(data))
def i2c_read(self, slave, register_address, data_length):
"""Read data from an I2C slave.
Args:
slave (:class:`hailo_platform.pyhailort.i2c_slaves.I2CSlave`): I2C slave
configuration.
register_address (int): The address of the register from which the data will be read.
data_length (int): The number of bytes to read.
Returns:
str: Data read from the I2C slave.
"""
c_slave = HcpControl._create_c_i2c_slave(slave)
with ExceptionWrapper():
return self._device.i2c_read(c_slave, register_address, data_length)
def read_register(self, address):
"""Read the value of a register from a given address.
Args:
address (int): Address to read register from.
Returns:
int: Value of the register
"""
register_value, = struct.unpack('!I', self.read_memory(address, type(self).WORD_SIZE))
return register_value
def set_bit(self, address, bit_index):
"""Set (turn on) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be set.
"""
register_value = self.read_register(address)
register_value |= 1 << bit_index
self.write_memory(address, struct.pack('!I', register_value))
def reset_bit(self, address, bit_index):
"""Reset (turn off) a specific bit at a register from a given address.
Args:
address (int) : Address of the register to modify.
bit_index (int) : Index of the bit that would be reset.
"""
register_value = self.read_register(address)
register_value &= ~(1 << bit_index)
self.write_memory(address, struct.pack('!I', register_value))
def firmware_update(self, firmware_binary, should_reset=True):
"""Update firmware binary on the flash.
Args:
firmware_binary (bytes): firmware binary stream.
should_reset (bool): Should a reset be performed after the update (to load the new firmware)
"""
with ExceptionWrapper():
return self._device.firmware_update(firmware_binary, len(firmware_binary), should_reset)
def second_stage_update(self, second_stage_binary):
"""Update second stage binary on the flash
Args:
second_stage_binary (bytes): second stage binary stream.
"""
with ExceptionWrapper():
return self._device.second_stage_update(second_stage_binary, len(second_stage_binary))
def store_sensor_config(self, section_index, reset_data_size, sensor_type, config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor configuration to Hailo chip flash memory.
Args:
section_index (int): Flash section index to write to. [0-6]
reset_data_size (int): Size of reset configuration.
sensor_type (:class:`~hailo_platform.pyhailort.pyhailort.SensorConfigTypes`): Sensor type.
config_file_path (str): Sensor configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
with ExceptionWrapper():
return self._device.sensor_store_config(section_index, reset_data_size, sensor_type, config_file_path,
config_height, config_width, config_fps, config_name)
def store_isp_config(self, reset_config_size, isp_static_config_file_path, isp_runtime_config_file_path,
config_height=0, config_width=0, config_fps=0, config_name=None):
"""Store sensor isp configuration to Hailo chip flash memory.
Args:
reset_config_size (int): Size of reset configuration.
isp_static_config_file_path (str): Sensor isp static configuration file path.
isp_runtime_config_file_path (str): Sensor isp runtime configuration file path.
config_height (int): Configuration resolution height.
config_width (int): Configuration resolution width.
config_fps (int): Configuration FPS.
config_name (str): Sensor configuration name.
"""
if config_name is None:
config_name = "UNINITIALIZED"
with ExceptionWrapper():
return self._device.store_isp_config(reset_config_size, config_height, config_width,
config_fps, isp_static_config_file_path, isp_runtime_config_file_path, config_name)
def get_sensor_sections_info(self):
"""Get sensor sections info from Hailo chip flash memory.
Returns:
Sensor sections info read from the chip flash memory.
"""
with ExceptionWrapper():
return self._device.sensor_get_sections_info()
def sensor_set_generic_i2c_slave(self, slave_address, register_address_size, bus_index, should_hold_bus, endianness):
"""Set a generic I2C slave for sensor usage.
Args:
sequence (int): Request/response sequence.
slave_address (int): The address of the I2C slave.
register_address_size (int): The size of the offset (in bytes).
bus_index (int): The number of the bus the I2C slave is behind.
should_hold_bus (bool): Hold the bus during the read.
endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`):
Big or little endian.
"""
with ExceptionWrapper():
return self._device.sensor_set_generic_i2c_slave(slave_address, register_address_size, bus_index, should_hold_bus, endianness)
def set_sensor_i2c_bus_index(self, sensor_type, i2c_bus_index):
"""Set the I2C bus to which the sensor of the specified type is connected.
Args:
sensor_type (:class:`~hailo_platform.pyhailort.pyhailort.SensorConfigTypes`): The sensor type.
i2c_bus_index (int): The I2C bus index of the sensor.
"""
with ExceptionWrapper():
return self._device.sensor_set_i2c_bus_index(sensor_type, i2c_bus_index)
def load_and_start_sensor(self, section_index):
"""Load the configuration with I2C in the section index.
Args:
section_index (int): Flash section index to load config from. [0-6]
"""
with ExceptionWrapper():
return self._device.sensor_load_and_start_config(section_index)
def reset_sensor(self, section_index):
"""Reset the sensor that is related to the section index config.
Args:
section_index (int): Flash section index to reset. [0-6]
"""
with ExceptionWrapper():
return self._device.sensor_reset(section_index)
def wd_enable(self, cpu_id):
"""Enable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.wd_enable(cpu_id)
def wd_disable(self, cpu_id):
"""Disable firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.wd_disable(cpu_id)
def wd_config(self, cpu_id, wd_cycles, wd_mode):
"""Configure a firmware watchdog.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
wd_cycles (int): number of cycles until watchdog is triggered.
wd_mode (int): 0 - HW/SW mode, 1 - HW only mode
"""
with ExceptionWrapper():
return self._device.wd_config(cpu_id, wd_cycles, wd_mode)
def previous_system_state(self, cpu_id):
"""Read the FW previous system state.
Args:
cpu_id (:class:`~hailo_platform.pyhailort.pyhailort.HailoCpuId`): 0 for App CPU, 1 for Core CPU.
"""
with ExceptionWrapper():
return self._device.previous_system_state(cpu_id)
def get_chip_temperature(self):
"""Returns the latest temperature measurements from the 2 internal temperature sensors of the Hailo chip.
Returns:
:class:`~hailo_platform.pyhailort.pyhailort.TemperatureInfo`:
Temperature in celsius of the 2 internal temperature sensors (TS), and a sample
count (a running 16-bit counter)
"""
with ExceptionWrapper():
return self._device.get_chip_temperature()
def get_extended_device_information(self):
with ExceptionWrapper():
response = self._device.get_extended_device_information()
device_information = ExtendedDeviceInformation(response.neural_network_core_clock_rate,
response.supported_features, response.boot_source, response.lcs, response.soc_id, response.eth_mac_address , response.unit_level_tracking_id, response.soc_pm_values)
return device_information
def _get_health_information(self):
with ExceptionWrapper():
response = self._device._get_health_information()
health_information = HealthInformation(response.overcurrent_protection_active, response.current_overcurrent_zone, response.red_overcurrent_threshold,
response.orange_overcurrent_threshold, response.temperature_throttling_active, response.current_temperature_zone, response.current_temperature_throttling_level,
response.temperature_throttling_levels, response.orange_temperature_threshold, response.orange_hysteresis_temperature_threshold,
response.red_temperature_threshold, response.red_hysteresis_temperature_threshold)
return health_information
def set_pause_frames(self, rx_pause_frames_enable):
"""Enable/Disable Pause frames.
Args:
rx_pause_frames_enable (bool): False for disable, True for enable.
"""
with ExceptionWrapper():
return self._device.set_pause_frames(rx_pause_frames_enable)
def test_chip_memories(self):
"""test all chip memories using smart BIST
"""
with ExceptionWrapper():
return self._device.test_chip_memories()
def _get_device_handle(self):
return self._device
class UdpHcpControl(HcpControl):
"""Control object that uses a HCP over UDP controller interface."""
def __init__(self, remote_ip, device=None, remote_control_port=22401, retries=2, response_timeout_seconds=10.0, ignore_socket_errors=False):
"""Initializes a new UdpControllerControl object.
Args:
remote_ip (str): The IPv4 address of the remote Hailo device (X.X.X.X).
remote_control_port (int, optional): The port that the remote Hailo device listens on.
response_timeout_seconds (float, optional): Number of seconds to wait until a response is received.
ignore_socket_errors (bool, optional): Ignore socket error (might be usefull for debugging).
"""
super(UdpHcpControl, self).__init__()
# In the C API we define the total amount of attempts, instead of the amount of retries.
max_number_of_attempts = retries + 1
response_timeout_milliseconds = int(response_timeout_seconds * 1000)
if device is None:
with ExceptionWrapper():
self.device = _pyhailort.Device.create_eth(remote_ip, remote_control_port,
response_timeout_milliseconds, max_number_of_attempts)
else:
self._device = device.device
self._device_id = self.identify()
class PcieHcpControl(HcpControl):
"""Control object that uses a HCP over PCIe controller interface."""
def __init__(self, device=None, device_info=None):
"""Initializes a new HailoPcieController object."""
super(PcieHcpControl, self).__init__()
if device_info is None:
device_info = InternalPcieDevice.scan_devices()[0]
if device is None:
with ExceptionWrapper():
self._device = _pyhailort.Device.create_pcie(device_info)
else:
self._device = device.device
self._device_id = self.identify()
def set_notification_callback(self, callback_func, notification_id, opaque):
"""Set a callback function to be called when a notification is received.
Args:
callback_func (function): Callback function with the parameters (device, notification, opaque).
Note that throwing exceptions is not supported and will cause the program to terminate with an error!
notification_id (NotificationId): Notification ID to register the callback to.
opauqe (object): User defined data.
Note:
The notifications thread is started and closed in the use_device() context, so
notifications can only be received there.
"""
with ExceptionWrapper():
return self._device.set_notification_callback(callback_func, notification_id, opaque)
def remove_notification_callback(self, notification_id):
"""Remove a notification callback which was already set.
Args:
notification_id (NotificationId): Notification ID to remove the callback from.
"""
with ExceptionWrapper():
return self._device.remove_notification_callback(notification_id)

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python
from builtins import str
import netifaces as ni
from netaddr import IPAddress, IPNetwork
# As defined in sockios.h
SIOCGIFTXQLEN = 0x8942
# Interface name is 16 bytes (including NULL)
SIOCGIFTXQLEN_FMT = "16sI"
class NoInterfaceError(Exception):
"""Raised by get_interface_from_ip when no matching interface was found"""
pass
def get_interface_from_ip(ip_address):
"""Returns the interface name associated with the given ip addressself.
Args:
ip_address (str): the IP address to query.
Returns:
str: The name of the interface matching the given IP address.
"""
skipped_ifaces = []
for interface in ni.interfaces():
if ni.AF_INET not in ni.ifaddresses(interface):
skipped_ifaces.append(interface)
continue
af_inet_values = ni.ifaddresses(interface)[ni.AF_INET][0]
ip_addr, netmask = af_inet_values['addr'], af_inet_values['netmask']
if is_ip_in_network(ip_addr, netmask, ip_address):
return str(interface)
raise NoInterfaceError('No interface for {} found among {}'.format(ip_address, skipped_ifaces))
def get_interface_address(interface_name):
"""Returns the interface address associated with the given interface name.
Args:
interface_name (str): the name of the interface to query.
Returns:
str: The IP address of the interface matching the given interface_name.
"""
af_inet_values = ni.ifaddresses(interface_name)[ni.AF_INET][0]
return af_inet_values['addr']
def is_ip_in_network(network_ip, netmask, ip_in_question):
"""Checks whether an IP address is located in a given network.
Args:
network_ip (str): the IP address of the network interface.
netmask (str): the netmask of the given networkself.
ip_in_question (str): the IP address to compare against the network.
Returns:
bool: whether the IP address belongs to the given network.
"""
netmask_bits = IPAddress(netmask).netmask_bits()
return IPAddress(ip_in_question) in IPNetwork('{}/{}'.format(network_ip, netmask_bits))

View File

@@ -0,0 +1,323 @@
#!/usr/bin/env python
"""
.. module:: hailo_control_protocol
:synopsis: Implements a Hailo Control Protocol message.
"""
from builtins import object
from enum import Enum, IntEnum
import struct
# Supported protocol and Firmware version of current SDK.
SUPPORTED_PROTOCOL_VERSION = 2
SUPPORTED_FW_MAJOR = 4
SUPPORTED_FW_MINOR = 8
SUPPORTED_FW_REVISION = 0
MEGA_MULTIPLIER = 1000.0 * 1000.0
class HailoControlProtocolException(Exception):
pass
class DeviceArchitectureTypes(IntEnum):
HAILO8_A0 = 0
HAILO8_B0 = 1
MERCURY_CA = 2
def __str__(self):
return self.name
class BoardInformation(object):
def __init__(self, protocol_version, fw_version_major, fw_version_minor, fw_version_revision,
logger_version, board_name, is_release, device_architecture, serial_number, part_number, product_name):
self.protocol_version = protocol_version
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.APP)
self.logger_version = logger_version
self.board_name = board_name
self.is_release = is_release
self.device_architecture = DeviceArchitectureTypes(device_architecture)
self.serial_number = serial_number
self.part_number = part_number
self.product_name = product_name
def _string_field_str(self, string_field):
# Return <Not Configured> if the string field is empty
return string_field.rstrip('\x00') or "<Not Configured>"
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Control Protocol Version: {}\n' \
'Firmware Version: {}\n' \
'Logger Version: {}\n' \
'Board Name: {}\n' \
'Device Architecture: {}\n' \
'Serial Number: {}\n' \
'Part Number: {}\n' \
'Product Name: {}\n'.format(
self.protocol_version,
self.firmware_version,
self.logger_version,
self.board_name.rstrip('\x00'),
str(self.device_architecture),
self._string_field_str(self.serial_number),
self._string_field_str(self.part_number),
self._string_field_str(self.product_name))
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
@staticmethod
def get_hw_arch_str(device_arch):
if device_arch == DeviceArchitectureTypes.HAILO8_B0:
return 'hailo8'
elif device_arch == DeviceArchitectureTypes.MERCURY_CA:
return 'mercury'
else:
raise HailoControlProtocolException("Unsupported device architecture.")
class CoreInformation(object):
def __init__(self, fw_version_major, fw_version_minor, fw_version_revision, is_release):
self.firmware_version = HailoFirmwareVersion.construct_from_params(fw_version_major, fw_version_minor, fw_version_revision, is_release, HailoFirmwareType.CORE)
self.is_release = is_release
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Core Firmware Version: {}'.format(
self.firmware_version)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class TemperatureThrottlingLevel(object):
def __init__(self, level_number, temperature_threshold, hysteresis_temperature_threshold, throttling_nn_clock_freq):
self.level_number = level_number
self.temperature_threshold = temperature_threshold
self.hysteresis_temperature_threshold = hysteresis_temperature_threshold
self.throttling_nn_clock_freq = throttling_nn_clock_freq
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Temperature Throttling Level {}: \n' \
'Temperature Threshold: {}\n' \
'Hysteresis Temperature Threshold: {}\n' \
'Throttling NN Clock Frequency: {}\n' \
.format(self.level_number, self.temperature_threshold, self.hysteresis_temperature_threshold, self.throttling_nn_clock_freq)
def __repr__(self):
return self.__str__()
class HealthInformation(object):
def __init__(self, overcurrent_protection_active, current_overcurrent_zone, red_overcurrent_threshold, orange_overcurrent_threshold,
temperature_throttling_active, current_temperature_zone, current_temperature_throttling_level,
temperature_throttling_levels, orange_temperature_threshold, orange_hysteresis_temperature_threshold,
red_temperature_threshold, red_hysteresis_temperature_threshold):
self.overcurrent_protection_active = overcurrent_protection_active
self.current_overcurrent_zone = current_overcurrent_zone
self.red_overcurrent_threshold = red_overcurrent_threshold
self.orange_overcurrent_threshold = orange_overcurrent_threshold
self.temperature_throttling_active = temperature_throttling_active
self.current_temperature_zone = current_temperature_zone
self.current_temperature_throttling_level = current_temperature_throttling_level
self.orange_temperature_threshold = orange_temperature_threshold
self.orange_hysteresis_temperature_threshold = orange_hysteresis_temperature_threshold
self.red_temperature_threshold = red_temperature_threshold
self.red_hysteresis_temperature_threshold = red_hysteresis_temperature_threshold
# Add TemperatureThrottlingLevel in case it has new throttling_nn_clock_freq. level_number can be used as only last
# levels can be with the same freq
self.temperature_throttling_levels = []
if self.temperature_throttling_active:
throttling_nn_clock_frequencies = []
for level_number, temperature_throttling_level in enumerate(temperature_throttling_levels):
if temperature_throttling_level.throttling_nn_clock_freq not in throttling_nn_clock_frequencies:
throttling_nn_clock_frequencies.append(temperature_throttling_level.throttling_nn_clock_freq)
self.temperature_throttling_levels.append(TemperatureThrottlingLevel(level_number,
temperature_throttling_level.temperature_threshold,
temperature_throttling_level.hysteresis_temperature_threshold,
temperature_throttling_level.throttling_nn_clock_freq))
def __repr__(self):
return self.__str__()
def __str__(self):
"""Returns:
str: Human readable string.
"""
temperature_throttling_levels_str = "\n".join(["\n\n{}\n".format(str(temperature_throttling_level)) for temperature_throttling_level in self.temperature_throttling_levels]) \
if self.temperature_throttling_active else "<Temperature throttling is disabled>"
return 'Overcurrent Protection Active: {}\n' \
'Overcurrent Protection Current Overcurrent Zone: {}\n' \
'Overcurrent Protection Red Threshold: {}\n' \
'Overcurrent Protection Orange Threshold: {}\n' \
'Temperature Protection Red Threshold: {}\n' \
'Temperature Protection Red Hysteresis Threshold: {}\n' \
'Temperature Protection Orange Threshold: {}\n' \
'Temperature Protection Orange Hysteresis Threshold: {}\n' \
'Temperature Protection Throttling State: {}\n' \
'Temperature Protection Current Zone: {}\n' \
'Temperature Protection Current Throttling Level: {}\n' \
'Temperature Protection Throttling Levels: {}' \
.format(self.overcurrent_protection_active, self.current_overcurrent_zone, self.red_overcurrent_threshold,
self.orange_overcurrent_threshold, self.red_temperature_threshold,
self.red_hysteresis_temperature_threshold, self.orange_temperature_threshold,
self.orange_hysteresis_temperature_threshold, self.temperature_throttling_active,
self.current_temperature_zone, self.current_temperature_throttling_level, temperature_throttling_levels_str)
class ExtendedDeviceInformation(object):
def __init__(self, neural_network_core_clock_rate, supported_features, boot_source, lcs, soc_id, eth_mac_address, unit_level_tracking_id, soc_pm_values):
self.neural_network_core_clock_rate = neural_network_core_clock_rate
self.supported_features = SupportedFeatures(supported_features)
self.boot_source = boot_source
self.lcs = lcs
self.soc_id = soc_id
self.eth_mac_address = eth_mac_address
self.unit_level_tracking_id = unit_level_tracking_id
self.soc_pm_values = soc_pm_values
def __str__(self):
"""Returns:
str: Human readable string.
"""
string = 'Neural Network Core Clock Rate: {}MHz\n' \
'{}' \
'Boot source: {}\n' \
'LCS: {}\n'.format(
self.neural_network_core_clock_rate / MEGA_MULTIPLIER,
str(self.supported_features),
str(self.boot_source.name),
str(self.lcs))
if any(self.soc_id):
string += 'SoC ID: ' + (self.soc_id.hex())
if any(self.eth_mac_address):
string += '\nMAC Address: ' + (":".join("{:02X}".format(i) for i in self.eth_mac_address))
if any(self.unit_level_tracking_id):
string += '\nULT ID: ' + (self.unit_level_tracking_id.hex())
if any(self.soc_pm_values):
string += '\nPM Values: ' + (self.soc_pm_values.hex())
return string
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
class HailoFirmwareMode(Enum):
"""Indication that firmware version is stable and official """
DEVELOP = 'develop'
RELEASE = 'release'
class HailoFirmwareType(Enum):
"""Indication the firmware type """
CORE = 'core'
APP = 'app'
class HailoFirmwareVersion(object):
"""Represents a Hailo chip firmware version."""
DEV_BIT = 0x80000000
CORE_BIT = 0x08000000
FW_VERSION_FORMAT = '<III'
def __init__(self, firmware_version_buffer, is_release, fw_type):
"""Initialize a new Hailo Firmware Version object.
Args:
firmware_version_buffer (str): A buffer containing the firmware version struct.
is_release (bool, optional): Flag indicating if firmware is at develop/release mode.
None indicates unknown
"""
self.major, self.minor, self.revision = struct.unpack(
self.FW_VERSION_FORMAT,
firmware_version_buffer)
self.fw_type = fw_type
self.mode = HailoFirmwareMode.RELEASE if is_release else HailoFirmwareMode.DEVELOP
self.revision &= ~(self.CORE_BIT | self.DEV_BIT)
def __str__(self):
"""Returns:
str: Firmware version in a human readable format.
"""
return '{}.{}.{} ({},{})'.format(self.major, self.minor, self.revision, self.mode.value, self.fw_type.value)
@classmethod
def construct_from_params(cls, major, minor, revision, is_release, fw_type):
"""Returns:
class HailoFirmwareVersion : with the given Firmware version.
"""
return cls(struct.pack(HailoFirmwareVersion.FW_VERSION_FORMAT, major, minor, revision), is_release, fw_type)
@property
def comparable_value(self):
"""A value that could be compared to other firmware versions."""
return (self.major << 64) + (self.minor << 32) + (self.revision)
def __hash__(self):
return self.comparable_value
def __eq__(self, other):
return self.comparable_value == other.comparable_value
# TODO: Required for Python2 BW compatibility (SDK-10038)
# This impl' comes by default in Python3
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self.comparable_value < other.comparable_value
def check_protocol_compatibility(self, other):
return ((self.major == other.major) and (self.minor == other.minor))
class SupportedFeatures(object):
def __init__(self, supported_features):
self.ethernet = supported_features.ethernet
self.mipi = supported_features.mipi
self.pcie = supported_features.pcie
self.current_monitoring = supported_features.current_monitoring
self.mdio = supported_features.mdio
def _feature_str(self, feature_name, is_feature_enabled):
return '{}: {}\n'.format(feature_name, 'Enabled' if is_feature_enabled else 'Disabled')
def __str__(self):
"""Returns:
str: Human readable string.
"""
return 'Device supported features: \n' + \
self._feature_str('Ethernet', self.ethernet) + \
self._feature_str('MIPI', self.mipi) + \
self._feature_str('PCIE', self.pcie) + \
self._feature_str('Current Monitoring', self.current_monitoring) + \
self._feature_str('MDIO', self.mdio)
def __repr__(self):
"""Returns:
str: Human readable string.
"""
return self.__str__()
def _is_feature_enabled(self, feature):
return (self.supported_features & feature) != 0

View File

@@ -0,0 +1,478 @@
#!/usr/bin/env python
"""Hailo hardware API"""
from __future__ import division
import gc
import os
from contextlib import contextmanager
from hailo_platform.pyhailort.control_object import UdpHcpControl, PcieHcpControl
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.pyhailort.hailo_control_protocol import BoardInformation
from hailo_platform.pyhailort.pyhailort import ConfiguredNetwork, InternalEthernetDevice, InternalPcieDevice, HailoRTTransformUtils, HailoUdpScan, HailoRTException
class InferenceTargets(object):
"""Enum-like class with all inference targets supported by the HailoRT."""
UNINITIALIZED = 'uninitialized'
UDP_CONTROLLER = 'udp'
PCIE_CONTROLLER = 'pcie'
class HailoHWObjectException(Exception):
"""Raised in any error related to Hailo hardware."""
pass
class HailoHWObject(object):
"""Abstract Hailo hardware device representation."""
NAME = InferenceTargets.UNINITIALIZED
IS_HARDWARE = True
def __init__(self):
"""Create the Hailo hardware object."""
self._last_interact_time = None
self._total_time = None
self._id = None
self._hw_arch = None
self._logger = default_logger()
self._debug = False
self._is_device_used = False
self._hef_loaded = False
# TODO: HRT-6310 Remove this.
def __eq__(self, other):
return type(self).NAME == other
@property
def name(self):
"""str: The name of this target. Valid values are defined by :class:`~hailo_platform.pyhailort.hw_object.InferenceTargets`"""
return type(self).NAME
@property
def is_hardware(self):
"""bool: Indicates this target runs on a physical hardware device."""
return type(self).IS_HARDWARE
@property
def device_id(self):
"""Getter for the device_id.
Returns:
str: A string ID of the device. BDF for PCIe devices, IP address for Ethernet devices, "Core" for core devices.
"""
return self._id
@property
def sorted_output_layer_names(self):
"""Getter for the property sorted_output_names.
Returns:
list of str: Sorted list of the output layer names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to sorted_output_layer_names is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_sorted_output_names()
@contextmanager
def use_device(self, *args, **kwargs):
"""A context manager that wraps the usage of the device (deprecated)."""
self._is_device_used = True
yield
self._is_device_used = False
def get_output_device_layer_to_original_layer_map(self):
"""Get a mapping between the device outputs to the layers' names they represent.
Returns:
dict: Keys are device output names and values are lists of layers' names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {stream_info.name : self._loaded_network_groups[0].get_vstream_names_from_stream_name(stream_info.name)
for stream_info in self.get_output_stream_infos()}
def get_original_layer_to_device_layer_map(self):
"""Get a mapping between the layer names and the device outputs that contain them.
Returns:
dict: Keys are the names of the layers and values are device outputs names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to layer names is only allowed when there is a single loaded network group")
return {vstream_info.name : self._loaded_network_groups[0].get_stream_names_from_vstream_name(vstream_info.name)
for vstream_info in self.get_output_vstream_infos()}
@property
def device_input_layers(self):
"""Get a list of the names of the device's inputs."""
return [layer.name for layer in self.get_input_stream_infos()]
@property
def device_output_layers(self):
"""Get a list of the names of the device's outputs."""
return [layer.name for layer in self.get_output_stream_infos()]
def hef_loaded(self):
"""Return True if this object has loaded the model HEF to the hardware device."""
return self._hef_loaded
def outputs_count(self):
"""Return the amount of output tensors that are returned from the hardware device for every
input image.
"""
return len(self.get_output_vstream_infos())
def _clear_shapes(self):
self._hw_consts = None
@property
def model_name(self):
"""Get the name of the current model.
Returns:
str: Model name.
"""
if len(self._loaded_network_groups) == 1:
return self._loaded_network_groups[0].name
raise HailoHWObjectException(
"This function is only supported when there is exactly 1 loaded network group. one should use HEF.get_network_group_names() / ConfiguredNetwork.name / ActivatedNetwork.name")
def get_output_shapes(self):
"""Get the model output shapes, as returned to the user (without any hardware padding).
Returns:
Tuple of output shapes, sorted by the output names.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Calling get_output_shapes is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_shapes()
class HailoChipObject(HailoHWObject):
"""Hailo hardware device representation"""
def __init__(self):
"""Create the Hailo Chip hardware object."""
super(HailoChipObject, self).__init__()
self._id = "Generic Hailo Device"
self._control_object = None
self._loaded_network_groups = []
self._creation_pid = os.getpid()
@property
def control(self):
""":class:`HailoControl <hailo_platform.pyhailort.control_object.HailoControl>`: Returns
the control object of this device, which implements the control API of the Hailo device.
.. attention:: Use the low level control API with care.
"""
if self._control_object is None:
raise HailoRTException(
"The device has been released and is not usable."
" Device is released when the function `release()` is called explicitly, or when created using a context manager and goes out of scope.")
return self._control_object
def get_all_input_layers_dtype(self):
"""Get the model inputs dtype.
Returns:
dict of :obj:'numpy.dtype': where the key is model input_layer name, and the value is dtype as the device expect to get for this input.
"""
return {stream.name: HailoRTTransformUtils.get_dtype(stream.data_bytes) for stream in self.get_input_stream_infos()}
def get_input_vstream_infos(self, network_name=None):
"""Get input vstreams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_vstream_infos(network_name=network_name)
def get_output_vstream_infos(self, network_name=None):
"""Get output vstreams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all output vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_vstream_infos(network_name=network_name)
def get_all_vstream_infos(self, network_name=None):
"""Get input and output vstreams information.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with all the information objects of all input and output vstreams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network vstream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_vstream_infos(network_name=network_name)
def get_input_stream_infos(self, network_name=None):
"""Get the input low-level streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
of all input low-level streams.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_input_stream_infos(network_name=network_name)
def get_output_stream_infos(self, network_name=None):
"""Get the output low-level streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.VStreamInfo`: with information objects
of all output low-level streams.
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_output_stream_infos(network_name=network_name)
def get_all_stream_infos(self, network_name=None):
"""Get input and output streams information of a specific network group.
Args:
network_name (str, optional): The name of the network to access. In case not given, all the networks in the network group will be addressed.
Returns:
If there is exactly one configured network group, returns a list of
:obj:`hailo_platform.pyhailort._pyhailort.StreamInfo`: with all the information objects of all input and output streams
"""
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network stream info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0].get_all_stream_infos(network_name=network_name)
@property
def loaded_network_groups(self):
"""Getter for the property _loaded_network_groups.
Returns:
list of :obj:`ConfiguredNetwork`: List of the the configured network groups loaded on the device.
"""
return self._loaded_network_groups
@property
def _loaded_network_group(self):
if len(self._loaded_network_groups) != 1:
raise HailoHWObjectException("Access to network layer info is only allowed when there is a single loaded network group")
return self._loaded_network_groups[0]
def configure(self, hef, configure_params_by_name={}):
"""Configures target device from HEF object.
Args:
hef (:class:`~hailo_platform.pyhailort.pyhailort.HEF`): HEF to configure the device from
configure_params_by_name (dict, optional): Maps between each net_group_name to configure_params. If not provided, default params will be applied
"""
if self._creation_pid != os.getpid():
raise HailoRTException("Device can only be configured from the process it was created in.")
configured_apps = self.control.configure(hef, configure_params_by_name)
self._hef_loaded = True
configured_networks = [ConfiguredNetwork(configured_app, self, hef) for configured_app in configured_apps]
self._loaded_network_groups.extend(configured_networks)
return configured_networks
def get_input_shape(self, name=None):
"""Get the input shape (not padded) of a network.
Args:
name (str, optional): The name of the desired input. If a name is not provided, return
the first input_dataflow shape.
Returns:
Tuple of integers representing the input_shape.
"""
if name is None:
name = self.get_input_vstream_infos()[0].name
for input_vstream in self.get_input_vstream_infos():
if input_vstream.name == name:
return input_vstream.shape
raise HailoHWObjectException("There is no input named {}! the input names are: {}".format(name,
[input_vstream.name for input_vstream in self.get_input_vstream_infos()]))
def get_index_from_name(self, name):
"""Get the index in the output list from the name.
Args:
name (str): The name of the output.
Returns:
int: The index of the layer name in the output list.
"""
try:
return self.sorted_output_layer_names.index(name)
except ValueError:
if len(self.sorted_output_layer_names) == 1:
# Case regard to SDK-9366 - see Jira for details.
self._logger.warning('Incorrect meta item - layer defuse_name does not match layer name.')
return 0
else:
raise HailoHWObjectException("Could not get index for outputs properly.")
def release(self):
"""
Release the allocated resources of the device. This function should be called when working with the device not as context-manager.
Note: After calling this function, the device will not be usable.
"""
if self._device is not None:
self._device.release()
self._device = None
self._control_object = None
class EthernetDevice(HailoChipObject):
"""Represents any Hailo hardware device that supports UDP control and dataflow."""
NAME = InferenceTargets.UDP_CONTROLLER
def __init__(
self,
remote_ip,
remote_control_port=22401):
"""Create the Hailo UDP hardware object.
Args:
remote_ip (str): Device IP address.
remote_control_port (int, optional): UDP port to which the device listens for control.
Defaults to 22401.
"""
super(EthernetDevice, self).__init__()
gc.collect()
self._remote_ip = remote_ip
self._remote_control_port = remote_control_port
# EthernetDevice __del__ function tries to release self._device.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
self._device = None
self._control_object = None
self._open_device()
self._id = "{}".format(self._remote_ip)
identity = self._control_object._device_id
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod
def scan_devices(interface_name, timeout_seconds=3):
"""Scans for all eth devices on a specific network interface.
Args:
interface_name (str): Interface to scan.
timeout_seconds (int, optional): timeout for scan operation. Defaults to 3.
Returns:
list of str: IPs of scanned devices.
"""
udp_scanner = HailoUdpScan()
return udp_scanner.scan_devices(interface_name, timeout_seconds=timeout_seconds)
def _open_device(self):
self._device = InternalEthernetDevice(self._remote_ip, self._remote_control_port)
self._control_object = UdpHcpControl(self._remote_ip, device=self._device, remote_control_port=self._remote_control_port)
def __enter__(self):
return self
def __exit__(self, *args):
self.release()
return False
def __del__(self):
self.release()
@property
def remote_ip(self):
"""Return the IP of the remote device."""
return self._remote_ip
class PcieDevice(HailoChipObject):
"""Hailo PCIe production device representation."""
NAME = InferenceTargets.PCIE_CONTROLLER
def __init__(
self,
device_info=None):
"""Create the Hailo PCIe hardware object.
Args:
device_info (:obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`, optional): Device info to create, call
:func:`PcieDevice.scan_devices` to get list of all available devices.
"""
super(PcieDevice, self).__init__()
gc.collect()
# PcieDevice __del__ function tries to release self._device.
# to avoid AttributeError if the __init__ func fails, we set it to None first.
# https://stackoverflow.com/questions/6409644/is-del-called-on-an-object-that-doesnt-complete-init
self._device = None
self._device_info = None
self._control_object = None
self._open_device(device_info)
# At this point self._device_info is already initialized
self._id = "{}".format(self._device_info)
identity = self._control_object._device_id
self._hw_arch = BoardInformation.get_hw_arch_str(identity.device_architecture)
@staticmethod
def scan_devices():
"""Scans for all pcie devices on the system.
Returns:
list of :obj:`hailo_platform.pyhailort.pyhailort.PcieDeviceInfo`
"""
return InternalPcieDevice.scan_devices()
def _open_device(self, device_info):
self._device = InternalPcieDevice(device_info)
self._device_info = self._device._device_info # Handeling a case where device_info is None
self._control_object = PcieHcpControl(device=self._device, device_info=self._device_info)
def __enter__(self):
return self
def __exit__(self, *args):
self.release()
return False
def __del__(self):
self.release()

View File

@@ -0,0 +1,191 @@
#!/usr/bin/env python
from builtins import object
import struct
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.pyhailort.pyhailort import Endianness
logger = default_logger()
#: Variable which defines that the I2C slave is not behind a switch.
NO_I2C_SWITCH = 5
class I2CSlavesException(Exception):
pass
class I2CSlave(object):
def __init__(self, name, bus_index, slave_address, switch_number=NO_I2C_SWITCH,
register_address_size=1, endianness=Endianness.LITTLE_ENDIAN,
should_hold_bus=False):
"""Initialize a class which describes an I2C slave.
Args:
name (str): The name of the I2C slave.
bus_index (int): The bus number the I2C slave is connected to.
slave_address (int): The address of the I2C slave.
switch_number (int): The number of the switch the i2c salve is connected to.
register_address_size (int): Slave register address length (in bytes).
endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`): The endianness of the slave.
should_hold_bus (bool): Should hold the bus during the read.
"""
self._name = name
self._bus_index = bus_index
self._slave_address = slave_address
self._switch_number = switch_number
self._register_address_size = register_address_size
self._endianness = endianness
self._should_hold_bus = should_hold_bus
def __repr__(self):
# Returning '' for the sphinx doc
return ''
@property
def name(self):
"""Get the name of the I2C slave.
Returns:
str: Name of the I2C slave.
"""
return self._name
@property
def bus_index(self):
"""Get bus index the I2C slave is connected to.
Returns:
int: Index of the bus the I2C slave is connected to.
"""
return self._bus_index
@property
def slave_address(self):
"""Get the address of the salve.
Returns:
int: The address of the I2C slave.
"""
return self._slave_address
@property
def register_address_size(self):
"""Get the slave register address length (in bytes). This number represents how many bytes are in the
register address the slave can access.
Returns:
int: Slave register address length.
Note:
Pay attention to the slave endianness (:class:`~hailo_platform.pyhailort.pyhailort.Endianness`).
"""
return self._register_address_size
@property
def switch_number(self):
"""Get the switch number the slave is connected to.
Returns:
int: The number of the switch the I2C is behind.
Note:
If :data:`NO_I2C_SWITCH` is returned, it means the slave is not behind a switch.
"""
return self._switch_number
@property
def endianness(self):
"""Get the slave endianness.
Returns:
:class:`~hailo_platform.pyhailort.pyhailort.Endianness`: The slave endianness.
"""
return self._endianness
@property
def should_hold_bus(self):
"""Returns a Boolean indicating if the bus will be held while reading from the slave.
Returns:
bool: True if the bus would be held, otherwise False.
"""
return self._should_hold_bus
# DVM's
#: Class which represents the MIPI AVDD I2C slave.
I2C_SLAVE_MIPI_AVDD = I2CSlave("DVM_MIPI_AVDD", 0, 0x40)
#: Class which represents the USB AVDD IO slave.
I2C_SLAVE_USB_AVDD_IO = I2CSlave("DVM_USB_AVDD_IO", 0, 0x41)
#: Class which represents the V_CORE slave.
I2C_SLAVE_VDD_CORE = I2CSlave("DVM_VDD_CORE", 0, 0x42)
#: Class which represents the VDD TOP slave.
I2C_SLAVE_VDD_TOP = I2CSlave("DVM_VDD_TOP", 0, 0x43)
#: Class which represents the MIPI AVDD_H I2C slave.
I2C_SLAVE_MIPI_AVDD_H = I2CSlave("DVM_MIPI_AVDD_H", 0, 0x44)
#: Class which represents the DVM USB AVDD IO HV slave.
I2C_SLAVE_USB_AVDD_IO_HV = I2CSlave("DVM_USB_AVDD_IO_HV", 0, 0x45)
#: Class which represents the DVM_VDDIO slave.
I2C_SLAVE_VDD_IO = I2CSlave("DVM_VDD_IO", 0, 0x46)
#: Class which represents the DVM_AVDD_H slave.
I2C_SLAVE_AVDD_H = I2CSlave("DVM_AVDD_H", 0, 0x47)
#: Class which represents the DVM_SDIO_VDDIO slave.
I2C_SLAVE_SDIO_VDD_IO = I2CSlave("DVM_SDIO_VDD_IO", 0, 0x4d)
#: Class which represents the DVM_SDIO_VDDIO slave.
I2C_SLAVE_M_DOT_2_OVERCURREN_PROTECTION = I2CSlave("M_DOT_2_OVERCURREN_PROTECTION", 0, 0x40)
#: Class which represents the I2S codec I2C slave.
I2C_SLAVE_I2S_CODEC = I2CSlave("I2S_codec", 1, 0x18, should_hold_bus=True)
#: Class which represents the I2C to gpio I2C slave.
I2C_SLAVE_I2C_TO_GPIO = I2CSlave("I2C_to_GPIO", 0, 0x22)
#: Class which represents the I2C switch slave.
I2C_SLAVE_SWITCH = I2CSlave("I2C_SWITCH", 1, 0x70)
#: Class which represents the I2C TEMP_sensor_0 slave.
I2C_SLAVE_TEMP_SENSOR_0 = I2CSlave("TEMP_sensor_0", 0, 0x29)
#: Class which represents the I2S TEMP_sensor_1 slave.
I2C_SLAVE_TEMP_SENSOR_1 = I2CSlave("TEMP_sensor_1", 0, 0x2A)
#: Class which represents the EEPROM I2C slave.
I2C_SLAVE_EEPROM = I2CSlave("EEPROM", 0, 0x50, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
# External hardware
#: Class which represents the raspicam I2C slave.
I2C_SLAVE_RASPICAM = I2CSlave("RaspiCam", 1, 0x36, switch_number=1, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
I2C_SLAVE_ONSEMI_CAMERA_AR0220 = I2CSlave('Onsemi', 1, 0x10, switch_number=0, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
I2C_SLAVE_ONSEMI_CAMERA_AS0149 = I2CSlave('Onsemi', 1, (0x90 >> 1), switch_number=0, register_address_size=2,
endianness=Endianness.BIG_ENDIAN)
def set_i2c_switch(control_object, slave, slave_switch=None):
"""Set the I2C switch in order to perform actions from the I2C slave.
Args:
control_object (:class:`~hailo_platform.pyhailort.control_object.HcpControl`): Control object
which communicates with the Hailo chip.
slave (:class:`I2CSlave`): Slave which the switch is set for.
slave_switch (:class:`I2CSlave`): The I2C slave for the switch it self. Defaults to
:data:`I2C_SLAVE_SWITCH`.
"""
I2C_SWITCH_REGISTER_SIZE = 1
if NO_I2C_SWITCH != slave.switch_number:
if not slave_switch:
slave_switch = I2C_SLAVE_SWITCH
# Set the switch value that should be written
switch_value = 1 << slave.switch_number
# Write new value to the switch
control_object.i2c_write(slave_switch, switch_value, struct.pack('b', switch_value))
# Read data from the switch, make sure write was successful
read_data, = struct.unpack('b', control_object.i2c_read(slave_switch, switch_value, I2C_SWITCH_REGISTER_SIZE))
if read_data != switch_value:
raise I2CSlavesException("Switch writing has failed. Read data is different then expected %s != %s" % (
read_data,
switch_value))

View File

@@ -0,0 +1,14 @@
from hailo_platform.pyhailort.pyhailort import (DvmTypes, PowerMeasurementTypes, # noqa F401
SamplingPeriod, AveragingFactor,
HailoPowerMeasurementUtils, MeasurementBufferIndex, HailoRTException)
# https://github.com/pybind/pybind11/issues/253
import re
def enum_to_dict(enum):
return {k: v for k, v in enum.__dict__.items() if not re.match("__(.*)", str(k)) and isinstance(v, enum)}
def _get_buffer_index_enum_member(index):
for name, member in enum_to_dict(MeasurementBufferIndex).items():
if int(member) == index:
return member
raise HailoRTException("Invalid index")

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class BenchmarkCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'benchmark')

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env python
"""Parses a configuration file that contains user or board configurations.
"""
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class FWConfigCommandCLI(HailortCliUtil):
"""CLI tool for changing the FW configuration (User Config)"""
def __init__(self, parser):
super().__init__(parser, 'fw-config')
class BoardConfigCommandCLI(HailortCliUtil):
"""CLI tool for changing the FW configuration (Board Config)"""
def __init__(self, parser):
super().__init__(parser, 'board-config')

View File

@@ -1,286 +0,0 @@
#!/usr/bin/env python
"""Parses a configuration file that contains the definitions of possible user configurations
Availabe in the firmware.
"""
from builtins import object
import json
from abc import ABCMeta
from collections import OrderedDict
from future.utils import with_metaclass
class ConfigSyntaxException(Exception):
"""Raised when there is a syntax error in the configuration file."""
pass
class UnsupportedConfigVersionException(Exception):
"""Raised when the version of the configuration file is not supported."""
pass
class ConfigFormattingException(Exception):
"""Raised when there is a formatting error in the firmware's configuration."""
pass
class ConfigDeserializationException(Exception):
"""Raised when there is an error while parsing a binary configuration."""
pass
class ConfigLine(with_metaclass(ABCMeta, object)):
"""An abstract config line class. Implements logic that is shared between a few types
of configuration lines.
"""
def __init__(self, config_name, config_id):
"""Initializes a new ConfigLine object.
Args:
config_name(str): Name defined for the configuration in the line.
config_id(int): Config ID (the integer representing the config).
"""
self._name = None
self.name = config_name
self._id = config_id
@property
def name(self):
"""Returns:
str: Name of the category.
"""
return self._name
@name.setter
def name(self, config_name):
if not (config_name.isalnum() or config_name[0].isalpha()):
raise ConfigSyntaxException('Configuration name must be alphanumeric (with a first '
'alphabetical character) received: {}'.format(
config_name))
self._name = config_name.lower()
@property
def id_value(self):
"""Returns:
int: Value of the entry's ID.
"""
return self._id
class ConfigEntry(ConfigLine):
"""A configuration entry."""
_PRIMITIVE_TYPES = {
1: 'int8_t',
2: 'int16_t',
4: 'int32_t'}
def __init__(self, entry_name, entry_id, category_id, size, length, sign, deserializer, length_before_serialization=None):
"""Initializes a new ConfigEntry object.
Args:
entry_name(str): Entry name.
entry_id(int): Entry ID (the integer representing the entry). (Should be 0-65535)
category_id(int): ID of the category that contains this entry. (Should be 0-65535)
size(int): Size of the entry in bytes. Only primitive sizes are supported.
length(int): Length of the entry, defined as an array if different than 0.
sign(bool): Is the primitive signed.
deserializer(str): The formatter to use when deserializing the entry.
length_before_serialization(int): Length of the entry before serialization, should be given only if this length
is different than size
"""
super(ConfigEntry, self).__init__(entry_name, entry_id)
self._category_id = category_id
if size not in self._PRIMITIVE_TYPES:
raise ConfigSyntaxException(
'Unsupported entry size. Supported sizes {}.'.format(list(self._PRIMITIVE_TYPES.keys())))
self._size = size
self._length = length
self._sign = sign
self._deserializer = deserializer
if length_before_serialization is None:
self._length_before_serialization = size
else:
self._length_before_serialization = length_before_serialization
@property
def deserializer(self):
"""Returns:
str: The formatter to use when deserializing the entry.
"""
return self._deserializer
@property
def primitive_type(self):
"""Returns:
str: The string representing the primitve C type of the entry.
"""
var_type = self._PRIMITIVE_TYPES[self._size]
if not self._sign:
var_type = 'u{}'.format(var_type)
return var_type
@property
def category_id(self):
"""Returns:
int: Entry id value.
"""
return self._category_id
@property
def length(self):
"""Returns:
int: Length of the entry, if this is different than zero, then the entry is an array.
"""
return self._length
@property
def total_size(self):
"""Returns:
int: Entry's total size in bytes.
"""
if self._length == 0:
return self._size
else:
return self._length * self._size
@property
def length_before_serialization(self):
"""Returns:
int: The length of the entry before serialization
"""
return self._length_before_serialization
class ConfigCategory(ConfigLine):
"""A configuration category that contains multiple configuration IDs"""
def __init__(self, category_name, category_id):
"""Initializes a new ConfigCategory object.
Args:
category_name(str): Category name.
category_id(int): Category ID (the integer representing the category).
"""
super(ConfigCategory, self).__init__(category_name, category_id)
self._config_entries = OrderedDict()
self._current_entry_id = 0
def append(self, entry_name, size, deserialize_as, length=0, sign=False, length_before_serialization=None):
"""Adds a new entry to the category
Args:
entry_name(str): Name of the appended configuration entry.
size(int): Size of the entry in bytes. Only primitive sizes are supported.
length(int): Length of the entry, defined as an array if different than 0.
sign(bool): Is the primitive signed.
deserialize_as(str): The formatter to use when deserializing the entry.
"""
config_entry = ConfigEntry(
entry_name,
self._current_entry_id,
self._id,
size,
length,
sign,
deserialize_as,
length_before_serialization)
self._config_entries[config_entry.name] = config_entry
self._current_entry_id += 1
@property
def entries(self):
"""Returns:
list of :obj:`ConfigEntry`: The entries in this category object.
"""
return self._config_entries
def __getitem__(self, key):
"""Returns:
int: The ID value of the requested entry key.
"""
return self._config_entries[key.lower()]
class FirmwareConfig(object):
"""This class wraps the configuration file that defines the firmware user config."""
_SUPPORTED_VERSION = [0]
_MAGIC_NUMBER = 0x1FF6A40B
def __init__(self, config_path):
"""Initializes a new FirmwareConfig object.
Args:
config_path(str): Path to a configuration file.
"""
config_file = open(config_path, 'r')
config_json = json.load(config_file, object_pairs_hook=OrderedDict)
self._current_category = None
self._next_category_id = 0
self._categories = OrderedDict()
self._parse_config_json(config_json)
def _parse_config_json(self, config_json):
"""Parses a json dictionary containing the configuration and assigns it to the
object attributes.
Args:
config_json(dict of str): A dictionary containing the configration file's content.
"""
try:
version = config_json['version']
except KeyError:
raise ConfigSyntaxException('Error: Version definition not found.')
if version not in self._SUPPORTED_VERSION:
raise UnsupportedConfigVersionException('Unsupported version: {}.\n'
'Supported versions: {}'.format(
version, self._SUPPORTED_VERSION))
self.version = version
try:
categories = config_json['categories']
except KeyError:
raise ConfigSyntaxException('Error: Categories definition not found.')
for i, category in enumerate(categories):
category_object = ConfigCategory(category, i)
try:
entries = config_json['categories'][category]['entries']
except KeyError:
raise ConfigSyntaxException('Error: Category {} does not contain entries.'.format(
category))
for entry in entries:
category_object.append(entry, **entries[entry])
self._categories[category_object.name] = category_object
@property
def supported_version(self):
"""Returns:
list of int: A list containing the supported configuration version.
"""
return self._SUPPORTED_VERSION
@property
def magic(self):
"""Returns:
int: Firmware configuration magic number value.
"""
return self._MAGIC_NUMBER
@property
def categories(self):
"""Returns:
list of :obj:`ConfigCategory`: List of configuration categories contained in the
firmware configuration.
"""
return self._categories
def __getitem__(self, key):
"""Returns:
:class:`sdk_client.hailo_sdk_client.tools.firmware.ConfigCategory: The category
corresponding to the requested key.
"""
return self._categories[key]

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env python
"""Parses a configuration file that contains camera sensor configurations in the FW.
"""
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class SensorConfigCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'sensor-config')

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env python
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class FWUpdaterCLI(HailortCliUtil):
"""Cli tool for firmware updates"""
def __init__(self, parser):
super().__init__(parser, 'fw-update')

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env python
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class SSBUpdaterCLI(HailortCliUtil):
"""Cli tool for second stage boot updates"""
def __init__(self, parser):
super().__init__(parser, 'ssb-update')

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env python
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class ScanCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'scan')
class ControlCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'fw-control')
class LoggerCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'fw-logger')
class MeasurePowerCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'measure-power')

View File

@@ -0,0 +1,14 @@
{
"network":
{
"static_netmask": "255.255.255.0",
"should_use_dhcp": false,
"mac_address": "80:00:DE:AD:BE:EF"
},
"system":
{
"name": "Hailo-8",
"supported_aspm_states": "ASPM L1 ONLY",
"temperature_throttling_enable": true
}
}

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python
from enum import Enum
from hailo_platform.common.tools.cmd_utils.base_utils import CmdUtilsBaseUtil
from hailo_platform.drivers.hw_object import EthernetDevice, PcieDevice
from hailo_platform.tools.hailocli.base_utils import CmdUtilsBaseUtil
from hailo_platform.pyhailort.hw_object import EthernetDevice, PcieDevice
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.drivers.hailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
from hailo_platform.pyhailort.pyhailort import PcieDeviceInfo, InternalPcieDevice
logger = default_logger()

View File

@@ -0,0 +1,70 @@
from hailo_platform.tools.hailocli.base_utils import HailortCliUtil
"""
HailoRTCLI matching commands in Hailo-CLI tool.
"""
class BenchmarkCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'benchmark')
class FWConfigCommandCLI(HailortCliUtil):
"""CLI tool for changing the FW configuration (User Config)"""
def __init__(self, parser):
super().__init__(parser, 'fw-config')
class BoardConfigCommandCLI(HailortCliUtil):
"""CLI tool for changing the FW configuration (Board Config)"""
def __init__(self, parser):
super().__init__(parser, 'board-config')
class ScanCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'scan')
class ControlCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'fw-control')
class LoggerCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'fw-logger')
class MeasurePowerCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'measure-power')
class RunCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'run')
class SensorConfigCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'sensor-config')
class FWUpdaterCLI(HailortCliUtil):
"""Cli tool for firmware updates"""
def __init__(self, parser):
super().__init__(parser, 'fw-update')
class SSBUpdaterCLI(HailortCliUtil):
"""Cli tool for second stage boot updates"""
def __init__(self, parser):
super().__init__(parser, 'ssb-update')
class UDPRateLimiterCLI(HailortCliUtil):
"""CLI tool for UDP rate limitation."""
def __init__(self, parser):
super().__init__(parser, 'udp-rate-limiter')

View File

@@ -5,17 +5,10 @@ import argcomplete
import sys
import hailo_platform
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil, Helper, HailortCliUtilError
from hailo_platform.tools.firmware.update_firmware import FWUpdaterCLI
from hailo_platform.tools.firmware.update_second_stage import SSBUpdaterCLI
from hailo_platform.tools.udp_rate_limiter import UDPRateLimiterCLI
from hailo_platform.tools.fw_control import ControlCommandCLI, ScanCommandCLI, LoggerCommandCLI, MeasurePowerCommandCLI
from hailo_platform.tools.run_command import RunCommandCLI
from hailo_platform.tools.infer_cli import InferCLI
from hailo_platform.tools.firmware.sensor_config import SensorConfigCommandCLI
from hailo_platform.tools.firmware.configure_firmware import FWConfigCommandCLI
from hailo_platform.tools.benchmark_command import BenchmarkCommandCLI
from hailo_platform.tools.hailocli.base_utils import HailortCliUtil, Helper, HailortCliUtilError
from hailo_platform.tools.hailocli.hailocli_commands import (FWUpdaterCLI, SSBUpdaterCLI, ControlCommandCLI, ScanCommandCLI,
LoggerCommandCLI, MeasurePowerCommandCLI, RunCommandCLI, SensorConfigCommandCLI,
FWConfigCommandCLI, BenchmarkCommandCLI, UDPRateLimiterCLI)
# Note: PlatformCommands are external dependencies in phase2-sdk/demos repo; don't change!
class PlatformCommands:
@@ -30,9 +23,7 @@ class PlatformCommands:
'fw-control': ('Useful firmware control operations', ControlCommandCLI),
'fw-logger': ('Download fw logs to a file', LoggerCommandCLI),
'scan': ('Scans for devices (Ethernet or PCIE)', ScanCommandCLI),
'broadcast': ('Scans for devices on a given interface (alias to \'hailo scan\')', ScanCommandCLI),
'sensor-config': ('Sensor configuration tool', SensorConfigCommandCLI),
'infer': ('Run a compiled network - infer command is deprecated and will be removed in a future release. Please use \'hailo run\' instead.', InferCLI),
'run': ('Run a compiled network', RunCommandCLI),
'benchmark': ('Measure basic performance on compiled network', BenchmarkCommandCLI),
'measure-power': ('Measures power consumption', MeasurePowerCommandCLI),

View File

@@ -1,54 +0,0 @@
from enum import Enum
from hailo_platform.common.tools.cmd_utils.hailo_device_utils import HailoDeviceCmdUtil
from hailo_platform.common.logger.logger import default_logger
from hailo_platform.tools.run_command import RunCommandCLI
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtilError
logger = default_logger()
class InferModes(Enum):
simple = 'simple'
performance = 'performance'
class InferCLI(HailoDeviceCmdUtil):
def __init__(self, parser):
super().__init__(parser, set_target_args=False)
self._hailortcli_run_command = RunCommandCLI(parser)
self._parser = parser
subparsers = parser.add_subparsers(title="Inference mode", dest="mode")
subparsers.required = True
simple_parser =subparsers.add_parser(InferModes.simple.value, help="'simple' mode is unsupported, please use 'hailo run' instead")
simple_parser.add_argument('--input-data-path', type=str, default=None,
help="unsupported argument.")
simple_parser.add_argument('--results-path', type=str, default=None,
help='Unsupported argument.')
simple_parser.add_argument('--config-path', type=str, required=True, help='Path to config HEF to infer with')
performance_parser = subparsers.add_parser(InferModes.performance.value,
help="infer command is deprecated and will be removed in a future release, please use 'hailo run' instead")
performance_parser.add_argument('--config-path', type=str, required=True,
help='Path to config HEF to infer with')
self.add_target_args(performance_parser)
performance_parser.add_argument('-t', '--streaming-time', type=float, default=10.0, help='For how long to stream in performance mode')
performance_parser.add_argument('--streaming-mode',
choices=['hw-only', 'full'],
default='full',
help='Whether to skip pre-infer and post-infer steps on host (hw-only) or do them (full)')
parser.set_defaults(func=self.run)
def run(self, args):
if InferModes[args.mode] == InferModes.simple:
logger.info("mode simple is deprecated please use \'hailo run\' instead.\n"
".npz and .npy format are unsupported, use binary file instead, you can use the following example:\n"
"\'hailo run --input-files [Input file path] [hef]\'.\n"
"for more information use \'hailo run --help\'.")
else:
self.validate_args(args)
argv = [args.config_path, "-t", str(int(args.streaming_time)), '-m', "streaming" if args.streaming_mode == 'full' else 'hw_only']
if args.target == 'udp':
argv += ['-d', args.target, '--ip', args.ip]
try:
self._hailortcli_run_command.run(argv)
except HailortCliUtilError as e:
print('\n'+ str(e))
return

View File

@@ -1,5 +0,0 @@
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
class RunCommandCLI(HailortCliUtil):
def __init__(self, parser):
super().__init__(parser, 'run')

View File

@@ -6,8 +6,7 @@ from __future__ import division
from builtins import object
from hailo_platform.common.tools.cmd_utils.base_utils import HailortCliUtil
from hailo_platform.drivers.hailort.pyhailort import ConfiguredNetwork, HEF, TrafficControl, INPUT_DATAFLOW_BASE_PORT
from hailo_platform.pyhailort.pyhailort import ConfiguredNetwork, HEF, TrafficControl, INPUT_DATAFLOW_BASE_PORT
DEFAULT_MAX_KBPS = 850e3
DEFAULT_MAX_KBPS_PAPRIKA_B0 = 160e3
@@ -41,7 +40,7 @@ class RateLimiterWrapper(object):
"""RateLimiterWrapper constructor.
Args:
configured_network_group (:class:`~hailo_platform.drivers.hailort.pyhailort.ConfiguredNetwork`): The
configured_network_group (:class:`~hailo_platform.pyhailort.pyhailort.ConfiguredNetwork`): The
target network_group.
fps (int): Frame rate.
fps_factor (float): Safety factor by which to multiply the calculated UDP rate.
@@ -114,9 +113,3 @@ class UDPRateLimiter(object):
results[port] = input_rates[stream_info.name] / BYTES_IN_Kbits
return results
class UDPRateLimiterCLI(HailortCliUtil):
"""CLI tool for UDP rate limitation."""
def __init__(self, parser):
super().__init__(parser, 'udp-rate-limiter')

View File

@@ -1,33 +0,0 @@
from __future__ import print_function
from builtins import object
import threading
class Watchdog(object):
def __init__(self, queues_to_close, timeout=20):
self.timeout = timeout
self._queues_to_close = queues_to_close
self._t = None
def do_expire(self):
for queue_to_close in self._queues_to_close:
queue_to_close.close()
def _expire(self):
print("\nWatchdog expire")
self.do_expire()
def start(self):
if self.timeout is not None:
self._t = threading.Timer(self.timeout, self._expire)
self._t.start()
else:
self._t = None
def stop(self):
if self._t is not None:
self._t.cancel()
def refresh(self):
self.stop()
self.start()

View File

@@ -35,8 +35,7 @@
"%matplotlib inline\n",
"import time\n",
"\n",
"from hailo_platform.drivers.hailo_controller.power_measurement import DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor # noqa F401\n",
"from hailo_platform import PcieDevice"
"from hailo_platform import PcieDevice, DvmTypes, PowerMeasurementTypes, SamplingPeriod, AveragingFactor, MeasurementBufferIndex # noqa F401\n"
]
},
{
@@ -88,7 +87,7 @@
"\n",
"In the following example, a periodic power measurement is taken.\n",
"\n",
"A measurement index is selected. It is a number between 0 and 3. The DVM is not given so the default DVM will be used, as explained above.\n"
"A measurement index is selected. It is a member of the enum class MeasurementBufferIndex (between 0 and 3). The DVM is not given so the default DVM will be used, as explained above.\n"
]
},
{
@@ -97,8 +96,8 @@
"metadata": {},
"outputs": [],
"source": [
"index = 0\n",
"target.control.set_power_measurement(index)"
"buffer_index = MeasurementBufferIndex.MEASUREMENT_BUFFER_INDEX_0\n",
"target.control.set_power_measurement(buffer_index=buffer_index)"
]
},
{
@@ -153,7 +152,7 @@
"for _ in range(10):\n",
" time.sleep(1)\n",
" # Get saved power measurement values from the firmware.\n",
" measurements = target.control.get_power_measurement(index, should_clear=should_clear)\n",
" measurements = target.control.get_power_measurement(buffer_index=buffer_index, should_clear=should_clear)\n",
" print('Average power is {} W. Min power is {} W. Max power is {} W.\\nAverage time between power samples is {} mS\\n'.format(measurements.average_value, measurements.min_value, measurements.max_value, measurements.average_time_value_milliseconds))\n",
" \n",
"# Stop performing periodic power measurement\n",

View File

@@ -9,7 +9,6 @@ importlib-resources==5.1.2
netaddr==0.8.0
netifaces==0.10.9
numpy==1.19.4
six==1.15.0
typing_extensions==4.1.1
verboselogs==1.7
virtualenv==20.4.3

View File

@@ -1,5 +1,5 @@
import os
import sys
import json
from setuptools import setup, find_packages
from wheel.bdist_wheel import bdist_wheel as orig_bdist_wheel
@@ -12,14 +12,27 @@ class NonPurePythonBDistWheel(orig_bdist_wheel):
self.root_is_pure = False
def _get_pyhailort_lib():
def _get_pyhailort_lib_path():
conf_file_path = os.path.join(os.path.abspath(os.path.dirname( __file__ )), "wheel_conf.json")
extension = {
"posix": "so",
"nt": "pyd", # Windows
}[os.name]
py = "".join(map(str, sys.version_info[:2]))
if not os.path.isfile(conf_file_path):
return None
return f"drivers/hailort/_pyhailort*{py}*.{extension}"
with open(conf_file_path, "r") as conf_file:
content = json.load(conf_file)
return f"../hailo_platform/pyhailort/_pyhailort*{content['py_version']}*{content['arch']}*.{extension}"
def _get_package_paths():
packages = []
pyhailort_lib = _get_pyhailort_lib_path()
if pyhailort_lib:
packages.append(pyhailort_lib)
packages.append("../hailo_tutorials/notebooks/*")
packages.append("../hailo_tutorials/hefs/*")
return packages
if __name__ == "__main__":
@@ -32,7 +45,7 @@ if __name__ == "__main__":
description="HailoRT",
entry_points={
"console_scripts": [
"hailo=hailo_platform.tools.cmd_utils.main:main",
"hailo=hailo_platform.tools.hailocli.main:main",
]
},
install_requires=[
@@ -41,16 +54,13 @@ if __name__ == "__main__":
"future",
"netaddr",
"netifaces",
"six",
"verboselogs",
# Pinned versions
"numpy==1.19.4",
],
name="hailort",
package_data={
"hailo_platform": [
_get_pyhailort_lib(), # packs _pyhailort library for _pyhailort imports
],
"hailo_platform": _get_package_paths(),
},
packages=find_packages(),
platforms=[
@@ -58,6 +68,6 @@ if __name__ == "__main__":
"linux_aarch64",
],
url="https://hailo.ai/",
version="4.6.0",
version="4.8.0",
zip_safe=False,
)

View File

@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0.0)
option(HAILO_BUILD_PYHAILORT_INTERNAL OFF)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
string(REPLACE "." "" dpython ${PYBIND11_PYTHON_VERSION}) # E.g "3.5" -> "35"
if(${dpython} LESS "38")
@@ -11,11 +13,20 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
endif()
set(PYHAILORT_DIR ${CMAKE_CURRENT_LIST_DIR})
add_subdirectory(internal)
pybind11_add_module(_pyhailort
pyhailort.cpp
device_api.cpp
hef_api.cpp
vstream_api.cpp
${HAILORT_COMMON_CPP_SOURCES}
)
set_target_properties(_pyhailort PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED YES
)
target_include_directories(_pyhailort
PRIVATE
$<BUILD_INTERFACE:${HAILORT_INC_DIR}>
@@ -30,3 +41,14 @@ if(WIN32)
endif()
target_compile_options(_pyhailort PRIVATE ${HAILORT_COMPILE_OPTIONS})
exclude_archive_libs_symbols(_pyhailort)
if (HAILO_BUILD_PYHAILORT_INTERNAL)
add_subdirectory(internal)
# copy files to venv
if(HAILO_BUILD_PYHAILORT_VENV)
add_custom_target(pyhailort_internal_venv ALL
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:_pyhailort_internal> ${PROJECT_SOURCE_DIR}/platform_internals/hailo_platform_internals/pyhailort/
)
add_dependencies(pyhailort_internal_venv _pyhailort_internal)
endif()
endif()

View File

@@ -18,22 +18,10 @@
namespace hailort
{
int convert_format_type_to_int(const hailo_format_type_t& type)
class HailoRTBindingsCommon
{
switch (type) {
case HAILO_FORMAT_TYPE_UINT8:
return 1;
case HAILO_FORMAT_TYPE_UINT16:
return 2;
case HAILO_FORMAT_TYPE_FLOAT32:
return 4;
default:
throw HailoRTStatusException("Invalid format type.");
}
}
std::string convert_format_type_to_string(const hailo_format_type_t& type)
public:
static std::string convert_format_type_to_string(const hailo_format_type_t &type)
{
switch (type) {
case HAILO_FORMAT_TYPE_UINT8:
@@ -47,7 +35,7 @@ std::string convert_format_type_to_string(const hailo_format_type_t& type)
}
}
std::vector<size_t> get_pybind_shape(const hailo_vstream_info_t& vstream_info, const hailo_format_t &user_format)
static std::vector<size_t> get_pybind_shape(const hailo_vstream_info_t& vstream_info, const hailo_format_t &user_format)
{
// We are using user_format instead of hw format inside the vstream_info
const auto shape = vstream_info.shape;
@@ -65,6 +53,12 @@ std::vector<size_t> get_pybind_shape(const hailo_vstream_info_t& vstream_info, c
}
}
static py::dtype get_dtype(const hailo_format_type_t &type)
{
return py::dtype(HailoRTBindingsCommon::convert_format_type_to_string(type));
}
};
} /* namespace hailort */
#endif /* _BINDINGS_COMMON_HPP_ */

View File

@@ -0,0 +1,568 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file device_api.cpp
* @brief implementations of binding to hailo device
*
**/
#include "device_api.hpp"
namespace hailort
{
DeviceWrapper DeviceWrapper::create_pcie(hailo_pcie_device_info_t &device_info)
{
auto device = Device::create_pcie(device_info);
VALIDATE_EXPECTED(device);
return DeviceWrapper(device.release());
}
DeviceWrapper DeviceWrapper::create_eth(std::string &device_address, uint16_t port,
uint32_t timeout_milliseconds, uint8_t max_number_of_attempts)
{
hailo_eth_device_info_t device_info = {};
/* Validate address length */
if (INET_ADDRSTRLEN < device_address.size()) {
EXIT_WITH_ERROR("device_address is too long")
}
device_info.host_address.sin_family = AF_INET;
device_info.host_address.sin_port = HAILO_ETH_PORT_ANY;
auto status = Socket::pton(AF_INET, HAILO_ETH_ADDRESS_ANY, &(device_info.host_address.sin_addr));
VALIDATE_STATUS(status);
device_info.device_address.sin_family = AF_INET;
device_info.device_address.sin_port = port;
status = Socket::pton(AF_INET, device_address.c_str(), &(device_info.device_address.sin_addr));
VALIDATE_STATUS(status);
device_info.timeout_millis = timeout_milliseconds;
device_info.max_number_of_attempts = max_number_of_attempts;
device_info.max_payload_size = HAILO_DEFAULT_ETH_MAX_PAYLOAD_SIZE;
auto device = Device::create_eth(device_info);
VALIDATE_EXPECTED(device);
return DeviceWrapper(device.release());
}
DeviceWrapper DeviceWrapper::create_core()
{
auto device = Device::create_core_device();
VALIDATE_EXPECTED(device);
return DeviceWrapper(device.release());
}
void DeviceWrapper::release()
{
m_device.reset();
}
/* Controls */
hailo_device_identity_t DeviceWrapper::identify()
{
auto board_info = device().identify();
VALIDATE_EXPECTED(board_info);
return board_info.release();
}
hailo_core_information_t DeviceWrapper::core_identify()
{
auto core_info = device().core_identify();
VALIDATE_EXPECTED(core_info);
return core_info.release();
}
void DeviceWrapper::set_fw_logger(hailo_fw_logger_level_t level, uint32_t interface_mask)
{
auto status = device().set_fw_logger(level, interface_mask);
VALIDATE_STATUS(status);
}
void DeviceWrapper::set_throttling_state(bool should_activate)
{
auto status = device().set_throttling_state(should_activate);
VALIDATE_STATUS(status);
}
bool DeviceWrapper::get_throttling_state()
{
auto is_active_expected = device().get_throttling_state();
VALIDATE_EXPECTED(is_active_expected);
return is_active_expected.release();
}
void DeviceWrapper::set_overcurrent_state(bool should_activate)
{
auto status = device().set_overcurrent_state(should_activate);
VALIDATE_STATUS(status);
}
bool DeviceWrapper::get_overcurrent_state()
{
auto is_required_expected = device().get_overcurrent_state();
VALIDATE_EXPECTED(is_required_expected);
return is_required_expected.release();
}
py::bytes DeviceWrapper::read_memory(uint32_t address, uint32_t length)
{
std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
VALIDATE_NOT_NULL(response);
MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(response->data())), length);
auto status = device().read_memory(address, data_view);
VALIDATE_STATUS(status);
return *response;
}
void DeviceWrapper::write_memory(uint32_t address, py::bytes data, uint32_t length)
{
auto status = device().write_memory(address, MemoryView(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(std::string(data).c_str())), length));
VALIDATE_STATUS(status);
}
void DeviceWrapper::test_chip_memories()
{
hailo_status status = device().test_chip_memories();
VALIDATE_STATUS(status);
}
void DeviceWrapper::i2c_write(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, py::bytes data,
uint32_t length)
{
VALIDATE_NOT_NULL(slave_config);
std::string data_str(data);
MemoryView data_view = MemoryView::create_const(data_str.c_str(), length);
auto status = device().i2c_write(*slave_config, register_address, data_view);
VALIDATE_STATUS(status);
}
py::bytes DeviceWrapper::i2c_read(hailo_i2c_slave_config_t *slave_config, uint32_t register_address, uint32_t length)
{
VALIDATE_NOT_NULL(slave_config);
std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(length, '\x00');
VALIDATE_NOT_NULL(response);
MemoryView data_view(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(response->data())), length);
auto status = device().i2c_read(*slave_config, register_address, data_view);
VALIDATE_STATUS(status);
return *response;
}
float32_t DeviceWrapper::power_measurement(hailo_dvm_options_t dvm,
hailo_power_measurement_types_t measurement_type)
{
auto measurement = device().power_measurement(dvm, measurement_type);
VALIDATE_EXPECTED(measurement);
return measurement.release();
}
void DeviceWrapper::start_power_measurement(hailo_averaging_factor_t averaging_factor, hailo_sampling_period_t sampling_period)
{
auto status = device().start_power_measurement(averaging_factor, sampling_period);
VALIDATE_STATUS(status);
}
void DeviceWrapper::set_power_measurement(hailo_measurement_buffer_index_t buffer_index, hailo_dvm_options_t dvm,
hailo_power_measurement_types_t measurement_type)
{
auto status = device().set_power_measurement(buffer_index,
dvm, measurement_type);
VALIDATE_STATUS(status);
}
PowerMeasurementData DeviceWrapper::get_power_measurement(hailo_measurement_buffer_index_t buffer_index, bool should_clear)
{
auto measurement_data = device().get_power_measurement(buffer_index,
should_clear);
VALIDATE_EXPECTED(measurement_data);
return PowerMeasurementData(measurement_data.release());
}
void DeviceWrapper::stop_power_measurement()
{
auto status = device().stop_power_measurement();
VALIDATE_STATUS(status);
}
void DeviceWrapper::reset(hailo_reset_device_mode_t mode)
{
auto status = device().reset(mode);
VALIDATE_STATUS(status);
}
hailo_fw_user_config_information_t DeviceWrapper::examine_user_config()
{
auto user_config_info = device().examine_user_config();
VALIDATE_EXPECTED(user_config_info);
return user_config_info.release();
}
py::bytes DeviceWrapper::read_user_config()
{
auto config_buffer = device().read_user_config();
VALIDATE_EXPECTED(config_buffer);
std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
const_cast<char*>(reinterpret_cast<const char*>(config_buffer->data())), config_buffer->size());
VALIDATE_NOT_NULL(response);
return *response;
}
void DeviceWrapper::write_user_config(py::bytes data)
{
std::string data_str(data);
MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
auto status = device().write_user_config(data_view);
VALIDATE_STATUS(status);
}
void DeviceWrapper::erase_user_config()
{
auto status = device().erase_user_config();
VALIDATE_STATUS(status);
}
py::bytes DeviceWrapper::read_board_config()
{
auto config_buffer = device().read_board_config();
VALIDATE_EXPECTED(config_buffer);
std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
const_cast<char*>(reinterpret_cast<const char*>(config_buffer->data())), config_buffer->size());
VALIDATE_NOT_NULL(response);
return *response;
}
void DeviceWrapper::write_board_config(py::bytes data)
{
std::string data_str(data);
MemoryView data_view = MemoryView::create_const(data_str.c_str(), data_str.size());
auto status = device().write_board_config(data_view);
VALIDATE_STATUS(status);
}
hailo_extended_device_information_t DeviceWrapper::get_extended_device_information()
{
auto extended_device_info = device().get_extended_device_information();
VALIDATE_EXPECTED(extended_device_info);
return extended_device_info.release();
}
hailo_health_info_t DeviceWrapper::get_health_information()
{
auto health_info = device().get_health_information();
VALIDATE_EXPECTED(health_info);
return health_info.release();
}
void DeviceWrapper::sensor_store_config(uint32_t section_index, uint32_t reset_data_size, uint32_t sensor_type, const std::string &config_file_path,
uint16_t config_height, uint16_t config_width, uint16_t config_fps, const std::string &config_name)
{
auto status = device().store_sensor_config(section_index, static_cast<hailo_sensor_types_t>(sensor_type), reset_data_size,
config_height, config_width, config_fps, config_file_path, config_name);
VALIDATE_STATUS(status);
}
void DeviceWrapper::store_isp_config(uint32_t reset_config_size, uint16_t config_height, uint16_t config_width, uint16_t config_fps,
const std::string &isp_static_config_file_path, const std::string &isp_runtime_config_file_path, const std::string &config_name)
{
auto status = device().store_isp_config(reset_config_size, config_height, config_width, config_fps,
isp_static_config_file_path, isp_runtime_config_file_path, config_name);
VALIDATE_STATUS(status);
}
py::bytes DeviceWrapper::sensor_get_sections_info()
{
auto buffer = device().sensor_get_sections_info();
VALIDATE_EXPECTED(buffer);
std::unique_ptr<std::string> response = make_unique_nothrow<std::string>(
const_cast<char*>(reinterpret_cast<const char*>(buffer->data())), buffer->size());
VALIDATE_NOT_NULL(response);
return *response;
}
void DeviceWrapper::sensor_set_i2c_bus_index(uint32_t sensor_type, uint32_t bus_index)
{
hailo_status status = device().sensor_set_i2c_bus_index(static_cast<hailo_sensor_types_t>(sensor_type), bus_index);
VALIDATE_STATUS(status);
}
void DeviceWrapper::sensor_load_and_start_config(uint32_t section_index)
{
auto status = device().sensor_load_and_start_config(section_index);
VALIDATE_STATUS(status);
}
void DeviceWrapper::sensor_reset(uint32_t section_index)
{
auto status = device().sensor_reset(section_index);
VALIDATE_STATUS(status);
}
void DeviceWrapper::sensor_set_generic_i2c_slave(uint16_t slave_address,
uint8_t register_address_size, uint8_t bus_index, uint8_t should_hold_bus, uint8_t endianness)
{
auto status = device().sensor_set_generic_i2c_slave(slave_address, register_address_size,
bus_index, should_hold_bus, endianness);
VALIDATE_STATUS(status);
}
void DeviceWrapper::firmware_update(py::bytes fw_bin, uint32_t fw_bin_length, bool should_reset)
{
auto status = device().firmware_update(MemoryView::create_const(std::string(fw_bin).c_str(), fw_bin_length),
should_reset);
VALIDATE_STATUS(status);
}
void DeviceWrapper::second_stage_update(py::bytes second_stage_bin, uint32_t second_stage_bin_length)
{
auto status = device().second_stage_update((uint8_t *)std::string(second_stage_bin).c_str(),
second_stage_bin_length);
VALIDATE_STATUS(status);
}
py::list DeviceWrapper::configure(const HefWrapper &hef,
const NetworkGroupsParamsMap &configure_params)
{
auto network_groups = device().configure(*hef.hef_ptr(), configure_params);
VALIDATE_EXPECTED(network_groups);
py::list results;
for (const auto &network_group : network_groups.value()) {
results.append(network_group.get());
}
return results;
}
void DeviceWrapper::set_pause_frames(bool rx_pause_frames_enable)
{
auto status = device().set_pause_frames(rx_pause_frames_enable);
VALIDATE_STATUS(status);
}
void DeviceWrapper::wd_enable(hailo_cpu_id_t cpu_id)
{
hailo_status status = device().wd_enable(cpu_id);
VALIDATE_STATUS(status);
}
void DeviceWrapper::wd_disable(hailo_cpu_id_t cpu_id)
{
hailo_status status = device().wd_disable(cpu_id);
VALIDATE_STATUS(status);
}
void DeviceWrapper::wd_config(hailo_cpu_id_t cpu_id, uint32_t wd_cycles, hailo_watchdog_mode_t wd_mode)
{
auto status = device().wd_config(cpu_id, wd_cycles, wd_mode);
VALIDATE_STATUS(status);
}
uint32_t DeviceWrapper::previous_system_state(hailo_cpu_id_t cpu_id)
{
auto system_state = device().previous_system_state(cpu_id);
VALIDATE_EXPECTED(system_state);
return system_state.release();
}
hailo_chip_temperature_info_t DeviceWrapper::get_chip_temperature()
{
auto temp_info = device().get_chip_temperature();
VALIDATE_EXPECTED(temp_info);
return temp_info.release();
}
void DeviceWrapper::set_notification_callback(const std::function<void(uintptr_t, const hailo_notification_t&, py::object)> &callback,
hailo_notification_id_t notification_id, py::object opaque)
{
// we capture opaque and move it because when opaque goes out of score it will be deleted,
// so capturing it ensures that it will not be deleted
hailo_status status = device().set_notification_callback(
[callback, op = std::move(opaque)] (Device &device, const hailo_notification_t &notification, void* opaque) {
(void)opaque;
callback((uintptr_t)(&device), notification, op);
}, notification_id, nullptr);
VALIDATE_STATUS(status);
}
void DeviceWrapper::remove_notification_callback(hailo_notification_id_t notification_id)
{
auto status = device().remove_notification_callback(notification_id);
VALIDATE_STATUS(status);
}
py::bytes DeviceWrapper::read_log(size_t byte_count, hailo_cpu_id_t cpu_id)
{
std::string response;
response.reserve(byte_count);
response.resize(byte_count);
MemoryView response_view ((&response[0]), byte_count);
auto response_size_expected = device().read_log(response_view, cpu_id);
VALIDATE_EXPECTED(response_size_expected);
response.resize(response_size_expected.release());
return py::bytes(response);
}
void DeviceWrapper::direct_write_memory(uint32_t address, py::bytes buffer)
{
const auto buffer_str = static_cast<std::string>(buffer);
hailo_status status = device().direct_write_memory(address, buffer_str.c_str(),
(uint32_t) (buffer_str.length()));
VALIDATE_STATUS(status);
}
py::bytes DeviceWrapper::direct_read_memory(uint32_t address, uint32_t size)
{
std::string buffer_str;
buffer_str.reserve(size);
buffer_str.resize(size);
hailo_status status = device().direct_read_memory(address, (char*)buffer_str.c_str(), size);
VALIDATE_STATUS(status);
buffer_str.resize(size);
return py::bytes(buffer_str);
}
void DeviceWrapper::add_to_python_module(py::module &m)
{
py::class_<DeviceWrapper>(m, "Device")
// C'tors
.def("create_pcie", &DeviceWrapper::create_pcie)
.def("create_eth", &DeviceWrapper::create_eth)
.def("create_core", &DeviceWrapper::create_core)
.def("release", &DeviceWrapper::release)
//HEF
.def("configure", &DeviceWrapper::configure)
// Controls
.def("identify", &DeviceWrapper::identify)
.def("core_identify", &DeviceWrapper::core_identify)
.def("set_fw_logger", &DeviceWrapper::set_fw_logger)
.def("read_memory", &DeviceWrapper::read_memory)
.def("write_memory", &DeviceWrapper::write_memory)
.def("power_measurement", &DeviceWrapper::power_measurement)
.def("start_power_measurement", &DeviceWrapper::start_power_measurement)
.def("stop_power_measurement", &DeviceWrapper::stop_power_measurement)
.def("set_power_measurement", &DeviceWrapper::set_power_measurement)
.def("get_power_measurement", &DeviceWrapper::get_power_measurement)
.def("firmware_update", &DeviceWrapper::firmware_update)
.def("second_stage_update", &DeviceWrapper::second_stage_update)
.def("examine_user_config", &DeviceWrapper::examine_user_config)
.def("read_user_config", &DeviceWrapper::read_user_config)
.def("write_user_config", &DeviceWrapper::write_user_config)
.def("erase_user_config", &DeviceWrapper::erase_user_config)
.def("read_board_config", &DeviceWrapper::read_board_config)
.def("write_board_config", &DeviceWrapper::write_board_config)
.def("i2c_write", &DeviceWrapper::i2c_write)
.def("i2c_read", &DeviceWrapper::i2c_read)
.def("sensor_store_config", &DeviceWrapper::sensor_store_config)
.def("store_isp_config", &DeviceWrapper::store_isp_config)
.def("sensor_set_i2c_bus_index", &DeviceWrapper::sensor_set_i2c_bus_index)
.def("sensor_load_and_start_config", &DeviceWrapper::sensor_load_and_start_config)
.def("sensor_reset", &DeviceWrapper::sensor_reset)
.def("sensor_set_generic_i2c_slave", &DeviceWrapper::sensor_set_generic_i2c_slave)
.def("sensor_get_sections_info", &DeviceWrapper::sensor_get_sections_info)
.def("reset", &DeviceWrapper::reset)
.def("wd_enable", &DeviceWrapper::wd_enable)
.def("wd_disable", &DeviceWrapper::wd_disable)
.def("wd_config", &DeviceWrapper::wd_config)
.def("previous_system_state", &DeviceWrapper::previous_system_state)
.def("get_chip_temperature", &DeviceWrapper::get_chip_temperature)
.def("get_extended_device_information", &DeviceWrapper::get_extended_device_information)
.def("set_pause_frames", &DeviceWrapper::set_pause_frames)
.def("test_chip_memories", &DeviceWrapper::test_chip_memories)
.def("_get_health_information", &DeviceWrapper::get_health_information)
.def("set_throttling_state", &DeviceWrapper::set_throttling_state)
.def("get_throttling_state", &DeviceWrapper::get_throttling_state)
.def("_set_overcurrent_state", &DeviceWrapper::set_overcurrent_state)
.def("_get_overcurrent_state", &DeviceWrapper::get_overcurrent_state)
.def("direct_write_memory", &DeviceWrapper::direct_write_memory)
.def("direct_read_memory", &DeviceWrapper::direct_read_memory)
.def("read_log", &DeviceWrapper::read_log, py::return_value_policy::move)
.def("set_notification_callback", &DeviceWrapper::set_notification_callback)
.def("remove_notification_callback", &DeviceWrapper::remove_notification_callback)
;
}
PowerMeasurementData::PowerMeasurementData(hailo_power_measurement_data_t &&c_power_data)
{
m_average_value = c_power_data.average_value;
m_average_time_value_milliseconds = c_power_data.average_time_value_milliseconds;
m_min_value = c_power_data.min_value;
m_max_value = c_power_data.max_value;
m_total_number_of_samples = c_power_data.total_number_of_samples;
}
/* Return a tuple that fully encodes the state of the object */
py::tuple PowerMeasurementData::get_state(const PowerMeasurementData &power_measurement_data)
{
return py::make_tuple(
power_measurement_data.m_average_value,
power_measurement_data.m_average_time_value_milliseconds,
power_measurement_data.m_min_value,
power_measurement_data.m_max_value,
power_measurement_data.m_total_number_of_samples);
}
PowerMeasurementData PowerMeasurementData::set_state(py::tuple t)
{
if (PowerMeasurementData::NUM_OF_MEMBERS != t.size())
throw std::runtime_error("Invalid power measurement data state!");
/* Create a new C++ instance */
hailo_power_measurement_data_t data;
data.average_value = t[0].cast<float32_t>();
data.average_time_value_milliseconds = t[1].cast<float32_t>();
data.min_value = t[2].cast<float32_t>();
data.max_value = t[3].cast<float32_t>();
data.total_number_of_samples = t[4].cast<uint32_t>();
return PowerMeasurementData(std::move(data));
}
bool PowerMeasurementData::equals(const PowerMeasurementData &other)
{
return ((this->m_average_value == other.m_average_value) &&
(this->m_average_time_value_milliseconds == other.m_average_time_value_milliseconds) &&
(this->m_min_value == other.m_min_value) &&
(this->m_max_value == other.m_max_value) &&
(this->m_total_number_of_samples == other.m_total_number_of_samples));
}
} /* namespace hailort */

Some files were not shown because too many files have changed in this diff Show More