COND_IF/WHILE_LOOP: Add nesting level limit

Nesting of if/while is bounded by MAX_NESTING,
set accoring to the TOSA level.

Change-Id: If9435a143ffa6bd7ba2e46a68542459b3d723b76
Signed-off-by: Dominic Symes <dominic.symes@arm.com>
diff --git a/chapters/control_flow.adoc b/chapters/control_flow.adoc
index e43ef51..9de9c72 100644
--- a/chapters/control_flow.adoc
+++ b/chapters/control_flow.adoc
@@ -19,17 +19,20 @@
 
 [source,c++]
 ----
+ERROR_IF(tosa_nesting_depth >= MAX_NESTING);
 ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(then_graph));
 ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(else_graph));
 ERROR_IF(tensor_list_shape(output_list) != tosa_output_shape(then_graph));
 ERROR_IF(tensor_list_shape(output_list) != tosa_output_shape(else_graph));
 ERROR_IF(tensor_size(shape) != 1);
 
+tosa_nesting_depth++;
 if (condition[0]) {
     tosa_execute_graph(then_graph, input_list, output_list);
 } else {
     tosa_execute_graph(else_graph, input_list, output_list);
 }
+tosa_nesting_depth--;
 ----
 
 ==== WHILE_LOOP
@@ -40,6 +43,7 @@
 
 [source,c++]
 ----
+ERROR_IF(tosa_nesting_depth >= MAX_NESTING);
 ERROR_IF(tensor_list_shape(input_list) != tosa_list_shape(output_list));
 ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(cond_graph));
 ERROR_IF(tensor_list_shape(input_list) != tosa_input_shape(body_graph));
@@ -54,11 +58,13 @@
 tensor_list_t list[];    // array of tensor lists indexed by iteration
 bool_t *condition[];     // array of condition tensors indexed by iteration
 list[i] = input_list;    // copy input data as list[0]
+tosa_nesting_depth++;
 tosa_execute_graph(cond_graph, list[i], [ condition[i] ]);   // initial condition
 while (condition[i][0]) {
     tosa_execute_graph(body_graph, list[i], list[i+1]);
     i = i+1;
     tosa_execute_graph(cond_graph, list[i], [ condition[i] ]);
 }
+tosa_nesting_depth--;
 output_list = list[i];
 ----
diff --git a/chapters/introduction.adoc b/chapters/introduction.adoc
index 955f310..62a9b2c 100644
--- a/chapters/introduction.adoc
+++ b/chapters/introduction.adoc
@@ -163,7 +163,8 @@
 bool tosa_test_compliance(tosa_graph_t graph, tosa_list_t input_list, tosa_level_t level) {
     shape_list_t output_list_spec = tosa_allocate_list(tosa_output_shape(graph));
     shape_list_t output_list_test = tosa_allocate_list(tosa_output_shape(graph));
-    tosa_graph_result = tosa_valid    // result starts as valid
+    tosa_graph_result = tosa_valid;    // result starts as valid
+    tosa_nesting_depth = 0;            // if/while nesting level
     tosa_execute_graph(graph, input_list, output_list_spec, level);
     if (tosa_graph_result == tosa_unpredictable) {
         return true;    // No requirement to match an unpredictable result
diff --git a/tools/tosa.py b/tools/tosa.py
index d01d9c2..acea04d 100644
--- a/tools/tosa.py
+++ b/tools/tosa.py
@@ -105,6 +105,7 @@
             'MAX_STRIDE': level.get("max_stride"),
             'MAX_SCALE': level.get("max_scale"),
             'MAX_LOG2_SIZE' : level.get("max_log2_size"),
+            'MAX_NESTING' : level.get("max_nesting"),
         }
         return TOSALevel(name, desc, maximums)
 
diff --git a/tosa.xml b/tosa.xml
index addbf92..cb56914 100644
--- a/tosa.xml
+++ b/tosa.xml
@@ -8,8 +8,8 @@
     <profile name="MT">Main Training</profile>
   </profiles>
   <levels>
-    <level name="none" max_rank="32" max_kernel="2147483647" max_stride="2147483647" max_scale="2048" max_log2_size="63">No level</level>
-    <level name="8K"   max_rank="6"  max_kernel="8192"       max_stride="8192"       max_scale="64"   max_log2_size="31">Level 8K</level>
+    <level name="none" max_rank="32" max_kernel="2147483647" max_stride="2147483647" max_scale="2048" max_log2_size="63" max_nesting="256">No level</level>
+    <level name="8K"   max_rank="6"  max_kernel="8192"       max_stride="8192"       max_scale="64"   max_log2_size="31" max_nesting="6">Level 8K</level>
   </levels>
   <operators>
     <operatorgroup name="tensor">
diff --git a/tosa.xsd b/tosa.xsd
index 40fd613..6aaf204 100644
--- a/tosa.xsd
+++ b/tosa.xsd
@@ -25,6 +25,7 @@
     <xs:enumeration value="MAX_SCALE"/>
     <xs:enumeration value="MAX_RANK"/>
     <xs:enumeration value="MAX_LOG2_SIZE"/>
+    <xs:enumeration value="MAX_NESTING"/>
   </xs:restriction>
 </xs:simpleType>
 
@@ -119,6 +120,7 @@
         <xs:attribute name="max_stride" type="xs:int" use="required"/>
         <xs:attribute name="max_scale"  type="xs:int" use="required"/>
         <xs:attribute name="max_log2_size" type="xs:int" use="required"/>
+        <xs:attribute name="max_nesting" type="xs:int" use="required"/>
       </xs:extension>
     </xs:simpleContent>
   </xs:complexType>