1
- from typing import Optional , List , Dict , Any , Type , Union , Set
1
+ from typing import Optional , List , Dict , Any , Type , Union , Set , TypeVar
2
2
import re
3
3
4
4
from xml .etree import ElementTree
10
10
11
11
from . import typemaps
12
12
13
+ CT = TypeVar ("CT" , bound = comp .Component )
13
14
14
15
# Expected IP-XACT namespaces. This parser is not strict about the exact version.
15
16
VALID_NS_REGEXES = [
19
20
]
20
21
21
22
class IPXACTImporter (RDLImporter ):
23
+ ns : str
22
24
23
- def __init__ (self , compiler : RDLCompiler ):
25
+ def __init__ (self , compiler : RDLCompiler ) -> None :
24
26
"""
25
27
Parameters
26
28
----------
@@ -29,10 +31,9 @@ def __init__(self, compiler: RDLCompiler):
29
31
"""
30
32
31
33
super ().__init__ (compiler )
32
- self .ns = None # type: str
33
34
self ._addressUnitBits = 8
34
35
self ._current_addressBlock_access = rdltypes .AccessType .rw
35
- self .remap_states_seen = set () # type : Set[str]
36
+ self .remap_states_seen : Set [str ] = set ()
36
37
37
38
@property
38
39
def src_ref (self ) -> SourceRefBase :
@@ -58,18 +59,23 @@ def import_file(self, path: str, remap_state: Optional[str] = None) -> None:
58
59
59
60
tree = ElementTree .parse (path )
60
61
61
- component = self .get_component (tree )
62
+ component = self .get_component (tree ) # type: ignore
62
63
63
64
memoryMaps = self .get_all_memoryMap (component )
64
65
66
+ comp_name = self .get_sanitized_element_name (component )
67
+ if not comp_name :
68
+ self .msg .fatal ("component is missing required tag 'name'" , self .src_ref )
69
+
65
70
for memoryMap in memoryMaps :
66
- comp_name = self .get_sanitized_element_name (component )
67
71
self .import_memoryMap (memoryMap , comp_name , remap_state )
68
72
69
73
70
74
def get_component (self , tree : ElementTree .ElementTree ) -> ElementTree .Element :
71
75
# Find <component> and determine namespace prefix
72
76
root = tree .getroot ()
77
+ assert root is not None
78
+
73
79
if get_local_name (root ) == "component" :
74
80
component = root
75
81
namespace = get_namespace (root )
@@ -116,6 +122,8 @@ def get_all_address_blocks(self, memoryMap: ElementTree.Element, remap_state: Op
116
122
memoryRemaps = memoryMap .findall (self .ns + "memoryRemap" )
117
123
for memoryRemap in memoryRemaps :
118
124
this_remapState = memoryRemap .get (self .ns + "state" )
125
+ if this_remapState is None :
126
+ continue
119
127
self .remap_states_seen .add (this_remapState )
120
128
if this_remapState == remap_state :
121
129
remap_addressBlocks = memoryRemap .findall (self .ns + "addressBlock" )
@@ -239,6 +247,8 @@ def parse_addressBlock(self, addressBlock: ElementTree.Element, name_prefix:str)
239
247
240
248
d = self .flatten_element_values (addressBlock )
241
249
name = self .get_sanitized_element_name (addressBlock )
250
+ if not name :
251
+ self .msg .fatal ("addressBlock is missing required tag 'name'" , self .src_ref )
242
252
243
253
if d .get ('usage' , None ) == "reserved" :
244
254
# 1685-2014 6.9.4.2-a.1.iii: defines the entire range of the
@@ -257,6 +267,7 @@ def parse_addressBlock(self, addressBlock: ElementTree.Element, name_prefix:str)
257
267
# Create named component definition
258
268
is_memory = d .get ('usage' , None ) == "memory"
259
269
type_name = name_prefix + name
270
+ C_def : Union [comp .Mem , comp .Addrmap ]
260
271
if is_memory :
261
272
C_def = self .create_mem_definition (type_name )
262
273
else :
@@ -295,9 +306,9 @@ def parse_addressBlock(self, addressBlock: ElementTree.Element, name_prefix:str)
295
306
if R :
296
307
self .add_child (C_def , R )
297
308
elif local_name == "registerFile" and not is_memory :
298
- R = self .parse_registerFile (child_el )
299
- if R :
300
- self .add_child (C_def , R )
309
+ RF = self .parse_registerFile (child_el )
310
+ if RF :
311
+ self .add_child (C_def , RF )
301
312
else :
302
313
self .msg .error (
303
314
"Invalid child element <%s> found in <%s:addressBlock>"
@@ -324,17 +335,19 @@ def parse_addressBlock(self, addressBlock: ElementTree.Element, name_prefix:str)
324
335
# Also convert to an instance, since this will be instantiated into the
325
336
# wrapper that represents the memoryMap
326
337
if is_memory :
327
- C = self .instantiate_mem (
338
+ assert isinstance (C_def , comp .Mem )
339
+ mem = self .instantiate_mem (
328
340
C_def ,
329
341
name , self .AU_to_bytes (d ['baseAddress' ])
330
342
)
343
+ return mem
331
344
else :
332
- C = self .instantiate_addrmap (
345
+ assert isinstance (C_def , comp .Addrmap )
346
+ am = self .instantiate_addrmap (
333
347
C_def ,
334
348
name , self .AU_to_bytes (d ['baseAddress' ])
335
349
)
336
-
337
- return C
350
+ return am
338
351
339
352
340
353
def parse_registerFile (self , registerFile : ElementTree .Element ) -> Optional [comp .Regfile ]:
@@ -361,6 +374,8 @@ def parse_registerFile(self, registerFile: ElementTree.Element) -> Optional[comp
361
374
362
375
d = self .flatten_element_values (registerFile )
363
376
name = self .get_sanitized_element_name (registerFile )
377
+ if not name :
378
+ self .msg .fatal ("registerFile is missing required tag 'name'" , self .src_ref )
364
379
365
380
# Check for required values
366
381
required = {'addressOffset' , 'range' }
@@ -402,9 +417,9 @@ def parse_registerFile(self, registerFile: ElementTree.Element) -> Optional[comp
402
417
if R :
403
418
self .add_child (C , R )
404
419
elif local_name == "registerFile" :
405
- R = self .parse_registerFile (child_el )
406
- if R :
407
- self .add_child (C , R )
420
+ RF = self .parse_registerFile (child_el )
421
+ if RF :
422
+ self .add_child (C , RF )
408
423
else :
409
424
self .msg .error (
410
425
"Invalid child element <%s> found in <%s:registerFile>"
@@ -456,6 +471,8 @@ def parse_register(self, register: ElementTree.Element) -> Optional[comp.Reg]:
456
471
457
472
d = self .flatten_element_values (register )
458
473
name = self .get_sanitized_element_name (register )
474
+ if not name :
475
+ self .msg .fatal ("register is missing required tag 'name'" , self .src_ref )
459
476
460
477
# Check for required values
461
478
required = {'addressOffset' , 'size' }
@@ -511,6 +528,8 @@ def parse_register(self, register: ElementTree.Element) -> Optional[comp.Reg]:
511
528
if local_name == "field" :
512
529
# This XML element is a field
513
530
field_name = self .get_sanitized_element_name (child_el )
531
+ if not field_name :
532
+ self .msg .fatal ("field is missing required tag 'name'" , self .src_ref )
514
533
field_tuples .append ((field_name , child_el ))
515
534
if field_name in field_names :
516
535
field_name_collisions .add (field_name )
@@ -650,6 +669,7 @@ def parse_field(
650
669
self .assign_property (C , "onwrite" , d ['modifiedWriteValue' ])
651
670
652
671
if 'enum_el' in d :
672
+ assert C .inst_name is not None
653
673
enum_type = self .parse_enumeratedValues (d ['enum_el' ], C .inst_name + "_enum_t" )
654
674
self .assign_property (C , "encode" , enum_type )
655
675
@@ -700,7 +720,7 @@ def parse_integer(self, s: str) -> int:
700
720
v *= multiplier [m .group (2 ).upper ()]
701
721
return v
702
722
703
- m = re .fullmatch (r"\d*'h([0-9a-f]+)" , s , re .I ) # type: ignore [unreachable]
723
+ m = re .fullmatch (r"\d*'h([0-9a-f]+)" , s , re .I )
704
724
if m :
705
725
return int (m .group (1 ), 16 )
706
726
@@ -890,6 +910,8 @@ def parse_enumeratedValues(self, enumeratedValues: ElementTree.Element, type_nam
890
910
d [local_name ] = self .parse_integer (get_text (child ))
891
911
892
912
name = self .get_sanitized_element_name (enumeratedValue )
913
+ if not name :
914
+ self .msg .fatal ("enumeratedValue is missing required tag 'name'" , self .src_ref )
893
915
894
916
# Check for required values
895
917
required = {'value' }
@@ -946,23 +968,23 @@ def AU_to_bytes(self, au: int) -> int:
946
968
return byte_units
947
969
948
970
949
- def memoryMap_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : comp . Component ) -> comp . Component :
971
+ def memoryMap_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : CT ) -> CT :
950
972
#pylint: disable=unused-argument
951
973
return component
952
974
953
- def addressBlock_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : comp . Component ) -> comp . Component :
975
+ def addressBlock_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : CT ) -> CT :
954
976
#pylint: disable=unused-argument
955
977
return component
956
978
957
- def registerFile_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : comp . Component ) -> comp . Component :
979
+ def registerFile_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : CT ) -> CT :
958
980
#pylint: disable=unused-argument
959
981
return component
960
982
961
- def register_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : comp . Component ) -> comp . Component :
983
+ def register_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : CT ) -> CT :
962
984
#pylint: disable=unused-argument
963
985
return component
964
986
965
- def field_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : comp . Component ) -> comp . Component :
987
+ def field_vendorExtensions (self , vendorExtensions : ElementTree .Element , component : CT ) -> CT :
966
988
#pylint: disable=unused-argument
967
989
return component
968
990
0 commit comments