@@ -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,10 +148,14 @@ 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
53- let usable_register_clusters = blocks
158+ let usable_register_clusters: Vec < _ > = blocks
54159 . iter ( )
55160 . flat_map ( |b| std:: iter:: repeat ( & b. name ) . zip ( b. registers . iter ( ) ) )
56161 . filter_map ( |( b, r) | {
@@ -66,13 +171,27 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
66171 return None ;
67172 } ;
68173
69- Some ( ( b, r. deref ( ) . clone ( ) , fields) )
70- } ) ;
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+ }
71188
72- for ( block_name, r, fields) in usable_register_clusters {
73- let mut fieldset_name = block_name. clone ( ) ;
189+ Some ( ( fs_name, r. deref ( ) , fields) )
190+ } )
191+ . collect ( ) ;
192+
193+ for ( fieldset_name, r, fields) in usable_register_clusters. clone ( ) {
74194 let mut field_name_counts: BTreeMap < String , usize > = BTreeMap :: new ( ) ;
75- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
76195 fieldsets. push ( ProtoFieldset {
77196 name : fieldset_name. clone ( ) ,
78197 description : r. description . clone ( ) ,
@@ -90,7 +209,6 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
90209 let mut enum_readwrite = None ;
91210
92211 let mut field_name = remove_placeholder ( & f. name ) ;
93-
94212 let field_name_count = field_name_counts. entry ( field_name. clone ( ) ) . or_insert ( 0 ) ;
95213 * field_name_count += 1 ;
96214 if * field_name_count > 1 {
@@ -209,74 +327,66 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
209327 continue ;
210328 }
211329
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)
330+ let names = crate :: svd2ir:: names ( & r, |r| & r. name ) ;
331+ let array = names. array ( ) ;
332+
333+ for ( offset, name) in names {
334+ let fieldset_name = if r. fields . is_some ( ) {
335+ let fieldset_full_name =
336+ fieldset_name ( proto. name . clone ( ) , name. clone ( ) ) ;
337+ let fieldset_name =
338+ inner_block_to_fieldset. get ( & fieldset_full_name) . unwrap ( ) ;
339+ Some ( fieldset_names. get ( fieldset_name) . unwrap ( ) . clone ( ) )
340+ } else {
341+ None
342+ } ;
343+
344+ let access = match r. properties . access {
345+ None => Access :: ReadWrite ,
346+ Some ( svd:: Access :: ReadOnly ) => Access :: Read ,
347+ Some ( svd:: Access :: WriteOnly ) => Access :: Write ,
348+ Some ( svd:: Access :: WriteOnce ) => Access :: Write ,
349+ Some ( svd:: Access :: ReadWrite ) => Access :: ReadWrite ,
350+ Some ( svd:: Access :: ReadWriteOnce ) => Access :: ReadWrite ,
351+ } ;
352+
353+ let block_item = BlockItem {
354+ name : name,
355+ description : r. description . clone ( ) ,
356+ array : array. clone ( ) ,
357+ byte_offset : r. address_offset + offset,
358+ inner : BlockItemInner :: Register ( Register {
359+ access, // todo
360+ bit_size : r. properties . size . unwrap_or ( 32 ) ,
361+ fieldset : fieldset_name. clone ( ) ,
362+ } ) ,
363+ } ;
364+
365+ block. items . push ( block_item)
366+ }
251367 }
252368 svd:: RegisterCluster :: Cluster ( c) => {
253369 if c. derived_from . is_some ( ) {
254370 warn ! ( "unsupported derived_from in clusters" ) ;
255371 continue ;
256372 }
257373
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- } ) ;
374+ let names = names ( c, |c| & c. name ) ;
375+ let array = names. array ( ) ;
376+
377+ for ( offset, cname) in names {
378+ let mut block_name = proto. name . clone ( ) ;
379+ block_name. push ( cname. clone ( ) ) ;
380+ let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
381+
382+ block. items . push ( BlockItem {
383+ name : cname. clone ( ) ,
384+ description : c. description . clone ( ) ,
385+ array : array. clone ( ) ,
386+ byte_offset : c. address_offset + offset,
387+ inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
388+ } ) ;
389+ }
280390 }
281391 }
282392 }
@@ -299,37 +409,31 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
299409 warn ! ( "unsupported derived_from in fieldset" ) ;
300410 }
301411
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- } ;
412+ let names = names ( f, |f| & f. name ) ;
413+ let array = names. array ( ) ;
310414
311- let field_name = remove_placeholder ( & f. name ) ;
415+ for ( offset, field_name) in names {
416+ let mut field = Field {
417+ name : field_name. clone ( ) ,
418+ description : f. description . clone ( ) ,
419+ bit_offset : BitOffset :: Regular ( f. bit_range . offset + offset) ,
420+ bit_size : f. bit_range . width ,
421+ array : array. clone ( ) ,
422+ enumm : None ,
423+ } ;
312424
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- } ;
425+ if !f. enumerated_values . is_empty ( ) {
426+ let mut enum_name = proto. name . clone ( ) ;
427+ enum_name. push ( field_name) ;
321428
322- if !f. enumerated_values . is_empty ( ) {
323- let mut enum_name = proto. name . clone ( ) ;
324- enum_name. push ( field_name) ;
429+ trace ! ( "finding enum {:?}" , enum_name) ;
430+ let enum_name = enum_names. get ( & enum_name) . unwrap ( ) . clone ( ) ;
431+ trace ! ( "found {:?}" , enum_name) ;
432+ field. enumm = Some ( enum_name. clone ( ) )
433+ }
325434
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 ( ) )
435+ fieldset. fields . push ( field)
330436 }
331-
332- fieldset. fields . push ( field)
333437 }
334438
335439 let fieldset_name = fieldset_names. get ( & proto. name ) . unwrap ( ) . clone ( ) ;
@@ -492,9 +596,11 @@ fn collect_blocks(
492596 continue ;
493597 }
494598
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 ) ;
599+ for ( _, block) in names ( c, |c| & c. name ) {
600+ let mut block_name = block_name. clone ( ) ;
601+ block_name. push ( block) ;
602+ collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
603+ }
498604 }
499605 }
500606}
@@ -588,7 +694,3 @@ pub fn namespace_names(peripheral: &PeripheralInfo, ir: &mut IR, namespace: Name
588694 }
589695 } ) ;
590696}
591-
592- pub fn remove_placeholder ( name : & str ) -> String {
593- name. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
594- }
0 commit comments