v4.8.0
This commit is contained in:
BIN
.hailort.png
Normal file
BIN
.hailort.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 143 KiB |
212
.logo.svg
212
.logo.svg
@@ -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 |
@@ -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)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="left">
|
||||
<img src=".logo.svg" />
|
||||
<img src=".hailort.png" />
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -125,6 +125,7 @@ private:
|
||||
};
|
||||
|
||||
using LatencyMeterPtr = std::shared_ptr<LatencyMeter>;
|
||||
using LatencyMetersMap = std::map<std::string, LatencyMeterPtr>;
|
||||
|
||||
} /* namespace hailort */
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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,
|
||||
|
||||
|
||||
124
hailort/drivers/win/include/Public.h
Normal file
124
hailort/drivers/win/include/Public.h
Normal 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;
|
||||
};
|
||||
10
hailort/drivers/win/include/hailo_pcie_version.h
Normal file
10
hailort/drivers/win/include/hailo_pcie_version.h
Normal 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_ */
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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}};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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([¶ms]() {
|
||||
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([¶ms]() {
|
||||
// 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([¶ms, hef_new, hef_old, power_sampling_period,
|
||||
run_subcommand->parse_complete_callback([¶ms, 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
@@ -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)) { \
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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',
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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'
|
||||
@@ -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())
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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))
|
||||
@@ -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
@@ -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')
|
||||
@@ -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')
|
||||
@@ -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]
|
||||
@@ -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')
|
||||
@@ -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')
|
||||
@@ -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')
|
||||
@@ -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')
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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')
|
||||
@@ -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),
|
||||
@@ -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
|
||||
@@ -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')
|
||||
@@ -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')
|
||||
|
||||
@@ -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()
|
||||
@@ -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",
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
568
hailort/libhailort/bindings/python/src/device_api.cpp
Normal file
568
hailort/libhailort/bindings/python/src/device_api.cpp
Normal 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 ¬ification, 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
Reference in New Issue
Block a user