@@ -48,6 +48,8 @@ def __init__(self, adb_path):
4848 try :
4949 # build a dictionary with all the adb nodes.
5050 self .adb_dict = ET .parse (adb_path )
51+ self ._build_xml_elements_dict ()
52+ self ._build_definitions ()
5153 # build a dictionary with only the adb nodes that contain segment id field.
5254 self .segment_id_nodes_dict = {}
5355 self ._build_nodes_with_seg_id ()
@@ -56,6 +58,93 @@ def __init__(self, adb_path):
5658 except Exception as _ :
5759 raise Exception ("Fail to parse the ADB file" )
5860
61+ def _build_xml_elements_dict (self ):
62+ self ._node_xml_elements = {}
63+ for xml_element in self .adb_dict .iter ('node' ):
64+ self ._node_xml_elements [xml_element .attrib ["name" ]] = xml_element
65+
66+ def _build_definitions (self ):
67+ # Create a list for 'inst_ifdef' (C like 'define' feature)
68+ self .ifdef_list = []
69+ for xml_element in self .adb_dict .iter ('config' ):
70+ if 'define' in xml_element .attrib and "=" not in xml_element .attrib ["define" ]:
71+ self .ifdef_list .append (xml_element .attrib ["define" ])
72+
73+ # Create a dict for 'inst_if' (C like 'define' feature)
74+ self .if_dict = {}
75+ for xml_element in self .adb_dict .iter ('config' ):
76+ if 'define' in xml_element .attrib and "=" in xml_element .attrib ["define" ]:
77+ define_name , define_value = xml_element .attrib ["define" ].split ("=" )
78+ self .if_dict [define_name ] = define_value
79+
80+ def _check_condition (self , left_operand , right_operand , condition ):
81+ """
82+ This method do the right logic according the given condition
83+ """
84+ if condition == ' EQ ' :
85+ return left_operand == right_operand
86+ elif condition == ' LESS ' :
87+ return left_operand < right_operand
88+ elif condition == ' LESS_EQ ' :
89+ return left_operand <= right_operand
90+ elif condition == ' GREAT_EQ ' :
91+ return left_operand >= right_operand
92+ elif condition == ' GREAT ' :
93+ return left_operand > right_operand
94+
95+ raise Exception ("unsupported condition {0}" .format (condition ))
96+
97+ def _get_condition_str (self , expression ):
98+ """
99+ This method return the right condition exist in the expression
100+ """
101+ if ' EQ ' in expression :
102+ return ' EQ '
103+ elif ' LESS ' in expression :
104+ return ' LESS '
105+ elif ' LESS_EQ ' in expression :
106+ return ' LESS_EQ '
107+ elif ' GREAT_EQ ' in expression :
108+ return ' GREAT_EQ '
109+ elif ' GREAT ' in expression :
110+ return ' GREAT '
111+
112+ raise Exception ("No condition found in expression {0}" .format (expression ))
113+
114+ def _check_single_expression (self , expression ):
115+ """
116+ The method check the condition type and perform the
117+ logic accordingly.
118+ """
119+ condition = self ._get_condition_str (expression )
120+ define_name , define_value = expression .split (condition )
121+ define_name = define_name .strip ()
122+ define_value = define_value .strip ()
123+
124+ # if operand not exist in the if dictionary its a value that we need to convert from str to int
125+ left_operand = int (self .if_dict [define_name ]) if define_name in self .if_dict else int (define_name )
126+ right_operand = int (self .if_dict [define_value ]) if define_value in self .if_dict else int (define_value )
127+ return self ._check_condition (left_operand , right_operand , condition )
128+
129+ def _check_expressions (self , inst_if_attrib ):
130+ """
131+ The method checks an expression and return True/False.
132+ Note that the method support only OR(s) or AND(s) but not together.
133+ """
134+ # assumption using 'OR' or 'AND' but not together
135+ expressions = []
136+ if ' OR ' in inst_if_attrib :
137+ expressions = inst_if_attrib .split (' OR ' )
138+ # check if one of the expressions is True return True
139+ return any ([self ._check_single_expression (expression ) for expression in expressions ])
140+ elif ' AND ' in inst_if_attrib :
141+ expressions = inst_if_attrib .split (' AND ' )
142+ # check if all of the expressions is True return True
143+ return all ([self ._check_single_expression (expression ) for expression in expressions ])
144+
145+ # if only one expression
146+ return self ._check_single_expression (inst_if_attrib )
147+
59148 def _fix_nodes_offset (self , nodes_dict ):
60149 """This method go over all the nodes in the dictionary and
61150 send them to offset fixing.
@@ -81,25 +170,35 @@ def _build_nodes_with_seg_id(self):
81170 self .segment_id_nodes_dict [node .attrib ["segment_id" ]] = adb_layout_item
82171
83172 def _retrieve_node_by_name (self , node_name ):
84- """This method go over all the nodes in the adb dictionary and return the node with the
173+ """This method return the node with the
85174 wanted name, if not found return None.
86175 """
87- for node in self .adb_dict . iter ( 'node' ) :
88- if node . attrib [ "name" ] == node_name :
89- return node
90- return None
176+ if node_name in self ._node_xml_elements :
177+ return self . _node_xml_elements [ node_name ]
178+ else : # Missing-nodes feature
179+ return None
91180
92181 def _build_subitems (self , node ):
93182 """This method build the subitems of the specific node
94183 """
95184 sub_items = []
96185 counter = 0
97186 for item in node :
187+ # Skip on elements that are excluded in the configuration ('inst_ifdef')
188+ if 'inst_ifdef' in item .attrib :
189+ if item .attrib ['inst_ifdef' ] not in self .ifdef_list :
190+ continue
191+ # Skip on elements that are excluded in the configuration ('inst_if')
192+ if 'inst_if' in item .attrib :
193+ if not self ._check_expressions (item .attrib ['inst_if' ]):
194+ continue
98195 if "low_bound" in item .attrib and "high_bound" in item .attrib :
99196 self ._extract_array_to_list (counter , item , sub_items )
100197 else :
101- sub_items .insert (counter , self ._node_to_AdbLayoutItem (item ))
102- counter += 1
198+ adb_layout_item = self ._node_to_AdbLayoutItem (item )
199+ if adb_layout_item :
200+ sub_items .insert (counter , adb_layout_item )
201+ counter += 1
103202 return sub_items
104203
105204 def _extract_array_to_list (self , index , item , subitems_list ):
@@ -118,12 +217,19 @@ def _extract_array_to_list(self, index, item, subitems_list):
118217 calculated_size = int (size / (end_index - start_index ))
119218 current_offset = offset
120219
220+
121221 for i in range (start_index , end_index ):
122222 adb_layout_item = AdbLayoutItem ()
123223 adb_layout_item .nodeDesc = self ._node_to_node_desc (item )
124224 adb_layout_item .name = name + "[" + str (i ) + "]"
125225 adb_layout_item .size = calculated_size
126226 adb_layout_item .offset = current_offset
227+ if "subnode" in item .attrib :
228+ sub_node = self ._retrieve_node_by_name (item .attrib ["subnode" ])
229+ if sub_node :
230+ if "attr_is_union" in sub_node .attrib :
231+ adb_layout_item .nodeDesc .isUnion = self ._parse_union (sub_node .attrib ["attr_is_union" ])
232+ adb_layout_item .subItems = self ._build_subitems (sub_node ) # List of the child items (for nodes only)
127233 subitems_list .insert (index , adb_layout_item )
128234 current_offset += calculated_size
129235 index += 1
0 commit comments