@@ -38,6 +38,107 @@ pub enum NamespaceMode {
3838 BlockWithRegsVals ,
3939}
4040
41+ fn remove_placeholder ( str : & str ) -> String {
42+ str. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
43+ }
44+
45+ fn names < T , F > ( array : & MaybeArray < T > , f : F ) -> ExpandedMaybeArray
46+ where
47+ F : Fn ( & T ) -> & str ,
48+ {
49+ fn is_numeric ( str : & String ) -> bool {
50+ str. chars ( ) . all ( |v| v. is_numeric ( ) )
51+ }
52+
53+ fn replace_placeholder ( str : & str , replacement : & str ) -> String {
54+ str. replace ( "%s" , replacement)
55+ }
56+
57+ fn as_array_name < ' a > (
58+ r : & str ,
59+ mut dim_element : impl Iterator < Item = & ' a String > ,
60+ ) -> Option < & str > {
61+ if let Some ( array) = r. strip_suffix ( "[%s]" ) {
62+ Some ( array)
63+ } else if let Some ( missed_array) = r. strip_suffix ( "%s" ) {
64+ // If all dimensions are numeric, the element is an IR
65+ // array because accessing with a number offset makes
66+ // sense.
67+ if dim_element. all ( is_numeric) {
68+ Some ( missed_array)
69+ } else {
70+ None
71+ }
72+ } else {
73+ None
74+ }
75+ }
76+
77+ match array {
78+ MaybeArray :: Single ( r) => ExpandedMaybeArray :: Single ( f ( r) . to_string ( ) ) ,
79+ MaybeArray :: Array ( r, dim_element) => {
80+ if let Some ( array_name) = as_array_name ( f ( r) , dim_element. dim_index . iter ( ) . flatten ( ) ) {
81+ ExpandedMaybeArray :: Array {
82+ name : array_name. to_string ( ) ,
83+ array : Array :: Regular ( RegularArray {
84+ len : dim_element. dim ,
85+ stride : dim_element. dim_increment ,
86+ } ) ,
87+ }
88+ } else {
89+ let offsets = ( 0 ..) . step_by ( dim_element. dim_increment as _ ) ;
90+
91+ let values = offsets
92+ . zip (
93+ dim_element
94+ . dim_index
95+ . iter ( )
96+ . flat_map ( |v| v. iter ( ) )
97+ . map ( |dim| replace_placeholder ( f ( r) , dim) ) ,
98+ )
99+ . collect ( ) ;
100+
101+ ExpandedMaybeArray :: Many ( values)
102+ }
103+ }
104+ }
105+ }
106+
107+ #[ derive( Clone ) ]
108+ enum ExpandedMaybeArray {
109+ Single ( String ) ,
110+ Array { name : String , array : Array } ,
111+ Many ( Vec < ( u32 , String ) > ) ,
112+ }
113+
114+ impl ExpandedMaybeArray {
115+ pub fn array ( & self ) -> Option < Array > {
116+ match self {
117+ ExpandedMaybeArray :: Array { array, .. } => Some ( array. clone ( ) ) ,
118+ _ => None ,
119+ }
120+ }
121+ }
122+
123+ impl IntoIterator for ExpandedMaybeArray {
124+ type Item = ( u32 , String ) ;
125+
126+ type IntoIter = std:: vec:: IntoIter < ( u32 , String ) > ;
127+
128+ fn into_iter ( self ) -> Self :: IntoIter {
129+ match self {
130+ ExpandedMaybeArray :: Single ( s) => vec ! [ ( 0 , s) ] . into_iter ( ) ,
131+ ExpandedMaybeArray :: Array { name, .. } => vec ! [ ( 0 , name) ] . into_iter ( ) ,
132+ ExpandedMaybeArray :: Many ( items) => items. into_iter ( ) ,
133+ }
134+ }
135+ }
136+
137+ fn fieldset_name ( mut block_name : Vec < String > , reg_name : String ) -> Vec < String > {
138+ block_name. push ( reg_name) ;
139+ block_name
140+ }
141+
41142pub fn convert_peripheral ( ir : & mut IR , p : & svd:: Peripheral ) -> anyhow:: Result < ( ) > {
42143 let mut blocks = Vec :: new ( ) ;
43144 let pname = p. header_struct_name . clone ( ) . unwrap_or ( p. name . clone ( ) ) ;
@@ -49,7 +150,11 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
49150 ) ;
50151
51152 let enum_from_name = enum_map ( & blocks) ;
153+
52154 let mut fieldsets: Vec < ProtoFieldset > = Vec :: new ( ) ;
155+ let mut inner_block_to_fieldset = BTreeMap :: new ( ) ;
156+ let mut used_fieldset_names = BTreeSet :: new ( ) ;
157+
53158 let mut enums: Vec < ProtoEnum > = Vec :: new ( ) ;
54159
55160 let usable_register_clusters = blocks
@@ -68,14 +173,35 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
68173 return None ;
69174 } ;
70175
71- Some ( ( b, r. deref ( ) . clone ( ) , fields) )
176+ let without_placeholder = remove_placeholder ( & r. name ) ;
177+ let mut fs_name = fieldset_name ( b. clone ( ) , without_placeholder. clone ( ) ) ;
178+
179+ let mut counter = 0 ;
180+ loop {
181+ if counter != 0 {
182+ let last = fs_name. last_mut ( ) . unwrap ( ) ;
183+ * last = format ! ( "{}_{}" , without_placeholder, counter) ;
184+ }
185+
186+ counter += 1 ;
187+
188+ if !used_fieldset_names. contains ( & fs_name) {
189+ break ;
190+ }
191+ }
192+
193+ used_fieldset_names. insert ( fs_name. clone ( ) ) ;
194+
195+ for ( _, full_name) in names ( r, |r| & r. name ) {
196+ let full_name: Vec < _ > = fieldset_name ( b. clone ( ) , full_name) ;
197+ inner_block_to_fieldset. insert ( full_name, fs_name. clone ( ) ) ;
198+ }
199+
200+ Some ( ( fs_name, r. deref ( ) , fields) )
72201 } ) ;
73202
74- for ( block_name, r, fields) in usable_register_clusters {
75- let mut fieldset_name = block_name. clone ( ) ;
203+ for ( fieldset_name, r, fields) in usable_register_clusters {
76204 let mut field_name_counts: BTreeMap < String , usize > = BTreeMap :: new ( ) ;
77- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
78-
79205 let mut out_fields = Vec :: with_capacity ( fields. len ( ) ) ;
80206
81207 for f in fields {
@@ -88,7 +214,6 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
88214 let mut enum_readwrite = None ;
89215
90216 let mut field_name = remove_placeholder ( & f. name ) ;
91-
92217 let field_name_count = field_name_counts. entry ( field_name. clone ( ) ) . or_insert ( 0 ) ;
93218 * field_name_count += 1 ;
94219 if * field_name_count > 1 {
@@ -219,37 +344,44 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
219344 continue ;
220345 }
221346
222- let block_item = create_block_item ( proto, & fieldset_names, r) ;
223- block. items . push ( block_item)
347+ let names = crate :: svd2ir:: names ( & r, |r| & r. name ) ;
348+ let array = names. array ( ) ;
349+
350+ for ( offset, name) in names {
351+ let block_item = create_block_item (
352+ name,
353+ offset,
354+ proto,
355+ & inner_block_to_fieldset,
356+ & fieldset_names,
357+ array. as_ref ( ) ,
358+ r,
359+ ) ;
360+ block. items . push ( block_item)
361+ }
224362 }
225363 svd:: RegisterCluster :: Cluster ( c) => {
226364 if c. derived_from . is_some ( ) {
227365 warn ! ( "unsupported derived_from in clusters" ) ;
228366 continue ;
229367 }
230368
231- let cname = remove_placeholder ( & c. name ) ;
232-
233- let array = if let svd:: Cluster :: Array ( _, dim) = c {
234- Some ( Array :: Regular ( RegularArray {
235- len : dim. dim ,
236- stride : dim. dim_increment ,
237- } ) )
238- } else {
239- None
240- } ;
241-
242- let mut block_name = proto. name . clone ( ) ;
243- block_name. push ( remove_placeholder ( & c. name ) ) ;
244- let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
245-
246- block. items . push ( BlockItem {
247- name : cname. clone ( ) ,
248- description : c. description . clone ( ) ,
249- array,
250- byte_offset : c. address_offset ,
251- inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
252- } ) ;
369+ let names = names ( c, |c| & c. name ) ;
370+ let array = names. array ( ) ;
371+
372+ for ( offset, cname) in names {
373+ let mut block_name = proto. name . clone ( ) ;
374+ block_name. push ( cname. clone ( ) ) ;
375+ let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
376+
377+ block. items . push ( BlockItem {
378+ name : cname. clone ( ) ,
379+ description : c. description . clone ( ) ,
380+ array : array. clone ( ) ,
381+ byte_offset : c. address_offset + offset,
382+ inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
383+ } ) ;
384+ }
253385 }
254386 }
255387 }
@@ -272,32 +404,26 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
272404 warn ! ( "unsupported derived_from in fieldset" ) ;
273405 }
274406
275- let array = if let svd:: Field :: Array ( _, dim) = f {
276- Some ( Array :: Regular ( RegularArray {
277- len : dim. dim ,
278- stride : dim. dim_increment ,
279- } ) )
280- } else {
281- None
282- } ;
407+ let names = names ( f, |f| & f. name ) ;
408+ let array = names. array ( ) ;
283409
284- let field_name = remove_placeholder ( & f. name ) ;
285-
286- let field = Field {
287- name : field_name. clone ( ) ,
288- description : f. description . clone ( ) ,
289- bit_offset : BitOffset :: Regular ( f. bit_range . offset ) ,
290- bit_size : f. bit_range . width ,
291- array,
292- enumm : enumm. as_ref ( ) . map ( |v| {
293- enum_names
294- . get ( v)
295- . cloned ( )
296- . expect ( "All enums have a unique-name mapping" )
297- } ) ,
298- } ;
410+ for ( offset, field_name) in names {
411+ let field = Field {
412+ name : field_name. clone ( ) ,
413+ description : f. description . clone ( ) ,
414+ bit_offset : BitOffset :: Regular ( f. bit_range . offset + offset) ,
415+ bit_size : f. bit_range . width ,
416+ array : array. clone ( ) ,
417+ enumm : enumm. as_ref ( ) . map ( |v| {
418+ enum_names
419+ . get ( v)
420+ . cloned ( )
421+ . expect ( "All enums have a unique-name mapping" )
422+ } ) ,
423+ } ;
299424
300- fieldset. fields . push ( field)
425+ fieldset. fields . push ( field)
426+ }
301427 }
302428
303429 let fieldset_name = fieldset_names. get ( & proto. name ) . unwrap ( ) . clone ( ) ;
@@ -336,23 +462,18 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
336462}
337463
338464fn create_block_item (
465+ name : String ,
466+ offset : u32 ,
339467 proto : & ProtoBlock ,
468+ inner_block_to_fieldset : & BTreeMap < Vec < String > , Vec < String > > ,
340469 fieldset_names : & BTreeMap < Vec < String > , String > ,
470+ array : Option < & Array > ,
341471 r : & MaybeArray < RegisterInfo > ,
342472) -> BlockItem {
343473 let fieldset_name = if r. fields . is_some ( ) {
344- let mut fieldset_name = proto. name . clone ( ) ;
345- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
346- Some ( fieldset_names. get ( & fieldset_name) . unwrap ( ) . clone ( ) )
347- } else {
348- None
349- } ;
350-
351- let array = if let svd:: Register :: Array ( _, dim) = r {
352- Some ( Array :: Regular ( RegularArray {
353- len : dim. dim ,
354- stride : dim. dim_increment ,
355- } ) )
474+ let fieldset_full_name = fieldset_name ( proto. name . clone ( ) , name. clone ( ) ) ;
475+ let fieldset_name = inner_block_to_fieldset. get ( & fieldset_full_name) . unwrap ( ) ;
476+ Some ( fieldset_names. get ( fieldset_name) . unwrap ( ) . clone ( ) )
356477 } else {
357478 None
358479 } ;
@@ -367,10 +488,10 @@ fn create_block_item(
367488 } ;
368489
369490 BlockItem {
370- name : remove_placeholder ( & r . name ) ,
491+ name : name,
371492 description : r. description . clone ( ) ,
372- array,
373- byte_offset : r. address_offset ,
493+ array : array . cloned ( ) ,
494+ byte_offset : r. address_offset + offset ,
374495 inner : BlockItemInner :: Register ( Register {
375496 access, // todo
376497 bit_size : r. properties . size . unwrap_or ( 32 ) ,
@@ -504,9 +625,11 @@ fn collect_blocks(
504625 continue ;
505626 }
506627
507- let mut block_name = block_name. clone ( ) ;
508- block_name. push ( remove_placeholder ( & c. name ) ) ;
509- collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
628+ for ( _, block) in names ( c, |c| & c. name ) {
629+ let mut block_name = block_name. clone ( ) ;
630+ block_name. push ( block) ;
631+ collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
632+ }
510633 }
511634 }
512635}
@@ -600,7 +723,3 @@ pub fn namespace_names(peripheral: &PeripheralInfo, ir: &mut IR, namespace: Name
600723 }
601724 } ) ;
602725}
603-
604- pub fn remove_placeholder ( name : & str ) -> String {
605- name. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
606- }
0 commit comments