@@ -3,7 +3,7 @@ use clap::ValueEnum;
33use log:: * ;
44use std:: collections:: { BTreeMap , BTreeSet } ;
55use std:: ops:: Deref ;
6- use svd_parser:: svd:: { self , PeripheralInfo } ;
6+ use svd_parser:: svd:: { self , MaybeArray , PeripheralInfo } ;
77
88use crate :: { ir:: * , transform} ;
99
@@ -36,6 +36,107 @@ pub enum NamespaceMode {
3636 BlockWithRegsVals ,
3737}
3838
39+ fn remove_placeholder ( str : & str ) -> String {
40+ str. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
41+ }
42+
43+ fn names < T , F > ( array : & MaybeArray < T > , f : F ) -> ExpandedMaybeArray
44+ where
45+ F : Fn ( & T ) -> & str ,
46+ {
47+ fn is_numeric ( str : & String ) -> bool {
48+ str. chars ( ) . all ( |v| v. is_numeric ( ) )
49+ }
50+
51+ fn replace_placeholder ( str : & str , replacement : & str ) -> String {
52+ str. replace ( "%s" , replacement)
53+ }
54+
55+ fn as_array_name < ' a > (
56+ r : & str ,
57+ mut dim_element : impl Iterator < Item = & ' a String > ,
58+ ) -> Option < & str > {
59+ if let Some ( array) = r. strip_suffix ( "[%s]" ) {
60+ Some ( array)
61+ } else if let Some ( missed_array) = r. strip_suffix ( "%s" ) {
62+ // If all dimensions are numeric, the element is an IR
63+ // array because accessing with a number offset makes
64+ // sense.
65+ if dim_element. all ( is_numeric) {
66+ Some ( missed_array)
67+ } else {
68+ None
69+ }
70+ } else {
71+ None
72+ }
73+ }
74+
75+ match array {
76+ MaybeArray :: Single ( r) => ExpandedMaybeArray :: Single ( f ( r) . to_string ( ) ) ,
77+ MaybeArray :: Array ( r, dim_element) => {
78+ if let Some ( array_name) = as_array_name ( f ( r) , dim_element. dim_index . iter ( ) . flatten ( ) ) {
79+ ExpandedMaybeArray :: Array {
80+ name : array_name. to_string ( ) ,
81+ array : Array :: Regular ( RegularArray {
82+ len : dim_element. dim ,
83+ stride : dim_element. dim_increment ,
84+ } ) ,
85+ }
86+ } else {
87+ let offsets = ( 0 ..) . step_by ( dim_element. dim_increment as _ ) ;
88+
89+ let values = offsets
90+ . zip (
91+ dim_element
92+ . dim_index
93+ . iter ( )
94+ . flat_map ( |v| v. iter ( ) )
95+ . map ( |dim| replace_placeholder ( f ( r) , dim) ) ,
96+ )
97+ . collect ( ) ;
98+
99+ ExpandedMaybeArray :: Many ( values)
100+ }
101+ }
102+ }
103+ }
104+
105+ #[ derive( Clone ) ]
106+ enum ExpandedMaybeArray {
107+ Single ( String ) ,
108+ Array { name : String , array : Array } ,
109+ Many ( Vec < ( u32 , String ) > ) ,
110+ }
111+
112+ impl ExpandedMaybeArray {
113+ pub fn array ( & self ) -> Option < Array > {
114+ match self {
115+ ExpandedMaybeArray :: Array { array, .. } => Some ( array. clone ( ) ) ,
116+ _ => None ,
117+ }
118+ }
119+ }
120+
121+ impl IntoIterator for ExpandedMaybeArray {
122+ type Item = ( u32 , String ) ;
123+
124+ type IntoIter = std:: vec:: IntoIter < ( u32 , String ) > ;
125+
126+ fn into_iter ( self ) -> Self :: IntoIter {
127+ match self {
128+ ExpandedMaybeArray :: Single ( s) => vec ! [ ( 0 , s) ] . into_iter ( ) ,
129+ ExpandedMaybeArray :: Array { name, .. } => vec ! [ ( 0 , name) ] . into_iter ( ) ,
130+ ExpandedMaybeArray :: Many ( items) => items. into_iter ( ) ,
131+ }
132+ }
133+ }
134+
135+ fn fieldset_name ( mut block_name : Vec < String > , reg_name : String ) -> Vec < String > {
136+ block_name. push ( reg_name) ;
137+ block_name
138+ }
139+
39140pub fn convert_peripheral ( ir : & mut IR , p : & svd:: Peripheral ) -> anyhow:: Result < ( ) > {
40141 let mut blocks = Vec :: new ( ) ;
41142 let pname = p. header_struct_name . clone ( ) . unwrap_or ( p. name . clone ( ) ) ;
@@ -47,7 +148,11 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
47148 ) ;
48149
49150 let enum_from_name = enum_map ( & blocks) ;
151+
50152 let mut fieldsets: Vec < ProtoFieldset > = Vec :: new ( ) ;
153+ let mut used_fieldset_names = BTreeMap :: new ( ) ;
154+ let mut inner_block_to_fieldset = BTreeMap :: new ( ) ;
155+
51156 let mut enums: Vec < ProtoEnum > = Vec :: new ( ) ;
52157
53158 let usable_register_clusters = blocks
@@ -66,13 +171,26 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
66171 return None ;
67172 } ;
68173
69- Some ( ( b, r. deref ( ) . clone ( ) , fields) )
174+ let mut fs_name = fieldset_name ( b. clone ( ) , remove_placeholder ( & r. name ) ) ;
175+
176+ let entry = used_fieldset_names. entry ( fs_name. clone ( ) ) . or_insert ( 0 ) ;
177+
178+ if * entry != 0 {
179+ fs_name. last_mut ( ) . map ( |v| * v = format ! ( "{v}{entry}" ) ) ;
180+ }
181+
182+ * entry += 1 ;
183+
184+ for ( _, full_name) in names ( r, |r| & r. name ) {
185+ let full_name: Vec < _ > = fieldset_name ( b. clone ( ) , full_name) ;
186+ inner_block_to_fieldset. insert ( full_name, fs_name. clone ( ) ) ;
187+ }
188+
189+ Some ( ( fs_name, r. deref ( ) , fields) )
70190 } ) ;
71191
72- for ( block_name, r, fields) in usable_register_clusters {
73- let mut fieldset_name = block_name. clone ( ) ;
192+ for ( fieldset_name, r, fields) in usable_register_clusters {
74193 let mut field_name_counts: BTreeMap < String , usize > = BTreeMap :: new ( ) ;
75- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
76194 fieldsets. push ( ProtoFieldset {
77195 name : fieldset_name. clone ( ) ,
78196 description : r. description . clone ( ) ,
@@ -90,7 +208,6 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
90208 let mut enum_readwrite = None ;
91209
92210 let mut field_name = remove_placeholder ( & f. name ) ;
93-
94211 let field_name_count = field_name_counts. entry ( field_name. clone ( ) ) . or_insert ( 0 ) ;
95212 * field_name_count += 1 ;
96213 if * field_name_count > 1 {
@@ -209,74 +326,66 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
209326 continue ;
210327 }
211328
212- let fieldset_name = if r. fields . is_some ( ) {
213- let mut fieldset_name = proto. name . clone ( ) ;
214- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
215- Some ( fieldset_names. get ( & fieldset_name) . unwrap ( ) . clone ( ) )
216- } else {
217- None
218- } ;
219-
220- let array = if let svd:: Register :: Array ( _, dim) = r {
221- Some ( Array :: Regular ( RegularArray {
222- len : dim. dim ,
223- stride : dim. dim_increment ,
224- } ) )
225- } else {
226- None
227- } ;
228-
229- let access = match r. properties . access {
230- None => Access :: ReadWrite ,
231- Some ( svd:: Access :: ReadOnly ) => Access :: Read ,
232- Some ( svd:: Access :: WriteOnly ) => Access :: Write ,
233- Some ( svd:: Access :: WriteOnce ) => Access :: Write ,
234- Some ( svd:: Access :: ReadWrite ) => Access :: ReadWrite ,
235- Some ( svd:: Access :: ReadWriteOnce ) => Access :: ReadWrite ,
236- } ;
237-
238- let block_item = BlockItem {
239- name : remove_placeholder ( & r. name ) ,
240- description : r. description . clone ( ) ,
241- array,
242- byte_offset : r. address_offset ,
243- inner : BlockItemInner :: Register ( Register {
244- access, // todo
245- bit_size : r. properties . size . unwrap_or ( 32 ) ,
246- fieldset : fieldset_name. clone ( ) ,
247- } ) ,
248- } ;
249-
250- block. items . push ( block_item)
329+ let names = crate :: svd2ir:: names ( & r, |r| & r. name ) ;
330+ let array = names. array ( ) ;
331+
332+ for ( offset, name) in names {
333+ let fieldset_name = if r. fields . is_some ( ) {
334+ let fieldset_full_name =
335+ fieldset_name ( proto. name . clone ( ) , name. clone ( ) ) ;
336+ let fieldset_name =
337+ inner_block_to_fieldset. get ( & fieldset_full_name) . unwrap ( ) ;
338+ Some ( fieldset_names. get ( fieldset_name) . unwrap ( ) . clone ( ) )
339+ } else {
340+ None
341+ } ;
342+
343+ let access = match r. properties . access {
344+ None => Access :: ReadWrite ,
345+ Some ( svd:: Access :: ReadOnly ) => Access :: Read ,
346+ Some ( svd:: Access :: WriteOnly ) => Access :: Write ,
347+ Some ( svd:: Access :: WriteOnce ) => Access :: Write ,
348+ Some ( svd:: Access :: ReadWrite ) => Access :: ReadWrite ,
349+ Some ( svd:: Access :: ReadWriteOnce ) => Access :: ReadWrite ,
350+ } ;
351+
352+ let block_item = BlockItem {
353+ name : name,
354+ description : r. description . clone ( ) ,
355+ array : array. clone ( ) ,
356+ byte_offset : r. address_offset + offset,
357+ inner : BlockItemInner :: Register ( Register {
358+ access, // todo
359+ bit_size : r. properties . size . unwrap_or ( 32 ) ,
360+ fieldset : fieldset_name. clone ( ) ,
361+ } ) ,
362+ } ;
363+
364+ block. items . push ( block_item)
365+ }
251366 }
252367 svd:: RegisterCluster :: Cluster ( c) => {
253368 if c. derived_from . is_some ( ) {
254369 warn ! ( "unsupported derived_from in clusters" ) ;
255370 continue ;
256371 }
257372
258- let cname = remove_placeholder ( & c. name ) ;
259-
260- let array = if let svd:: Cluster :: Array ( _, dim) = c {
261- Some ( Array :: Regular ( RegularArray {
262- len : dim. dim ,
263- stride : dim. dim_increment ,
264- } ) )
265- } else {
266- None
267- } ;
268-
269- let mut block_name = proto. name . clone ( ) ;
270- block_name. push ( remove_placeholder ( & c. name ) ) ;
271- let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
272-
273- block. items . push ( BlockItem {
274- name : cname. clone ( ) ,
275- description : c. description . clone ( ) ,
276- array,
277- byte_offset : c. address_offset ,
278- inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
279- } ) ;
373+ let names = names ( c, |c| & c. name ) ;
374+ let array = names. array ( ) ;
375+
376+ for ( offset, cname) in names {
377+ let mut block_name = proto. name . clone ( ) ;
378+ block_name. push ( cname. clone ( ) ) ;
379+ let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
380+
381+ block. items . push ( BlockItem {
382+ name : cname. clone ( ) ,
383+ description : c. description . clone ( ) ,
384+ array : array. clone ( ) ,
385+ byte_offset : c. address_offset + offset,
386+ inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
387+ } ) ;
388+ }
280389 }
281390 }
282391 }
@@ -299,37 +408,31 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
299408 warn ! ( "unsupported derived_from in fieldset" ) ;
300409 }
301410
302- let array = if let svd:: Field :: Array ( _, dim) = f {
303- Some ( Array :: Regular ( RegularArray {
304- len : dim. dim ,
305- stride : dim. dim_increment ,
306- } ) )
307- } else {
308- None
309- } ;
411+ let names = names ( f, |f| & f. name ) ;
412+ let array = names. array ( ) ;
310413
311- let field_name = remove_placeholder ( & f. name ) ;
414+ for ( offset, field_name) in names {
415+ let mut field = Field {
416+ name : field_name. clone ( ) ,
417+ description : f. description . clone ( ) ,
418+ bit_offset : BitOffset :: Regular ( f. bit_range . offset + offset) ,
419+ bit_size : f. bit_range . width ,
420+ array : array. clone ( ) ,
421+ enumm : None ,
422+ } ;
312423
313- let mut field = Field {
314- name : field_name. clone ( ) ,
315- description : f. description . clone ( ) ,
316- bit_offset : BitOffset :: Regular ( f. bit_range . offset ) ,
317- bit_size : f. bit_range . width ,
318- array,
319- enumm : None ,
320- } ;
424+ if !f. enumerated_values . is_empty ( ) {
425+ let mut enum_name = proto. name . clone ( ) ;
426+ enum_name. push ( field_name) ;
321427
322- if !f. enumerated_values . is_empty ( ) {
323- let mut enum_name = proto. name . clone ( ) ;
324- enum_name. push ( field_name) ;
428+ trace ! ( "finding enum {:?}" , enum_name) ;
429+ let enum_name = enum_names. get ( & enum_name) . unwrap ( ) . clone ( ) ;
430+ trace ! ( "found {:?}" , enum_name) ;
431+ field. enumm = Some ( enum_name. clone ( ) )
432+ }
325433
326- trace ! ( "finding enum {:?}" , enum_name) ;
327- let enum_name = enum_names. get ( & enum_name) . unwrap ( ) . clone ( ) ;
328- trace ! ( "found {:?}" , enum_name) ;
329- field. enumm = Some ( enum_name. clone ( ) )
434+ fieldset. fields . push ( field)
330435 }
331-
332- fieldset. fields . push ( field)
333436 }
334437
335438 let fieldset_name = fieldset_names. get ( & proto. name ) . unwrap ( ) . clone ( ) ;
@@ -492,9 +595,11 @@ fn collect_blocks(
492595 continue ;
493596 }
494597
495- let mut block_name = block_name. clone ( ) ;
496- block_name. push ( remove_placeholder ( & c. name ) ) ;
497- collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
598+ for ( _, block) in names ( c, |c| & c. name ) {
599+ let mut block_name = block_name. clone ( ) ;
600+ block_name. push ( block) ;
601+ collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
602+ }
498603 }
499604 }
500605}
@@ -588,7 +693,3 @@ pub fn namespace_names(peripheral: &PeripheralInfo, ir: &mut IR, namespace: Name
588693 }
589694 } ) ;
590695}
591-
592- pub fn remove_placeholder ( name : & str ) -> String {
593- name. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
594- }
0 commit comments