@@ -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 inner_block_to_fieldset = BTreeMap :: new ( ) ;
154+ let mut used_fieldset_names = BTreeSet :: new ( ) ;
155+
51156 let mut enums: Vec < ProtoEnum > = Vec :: new ( ) ;
52157
53158 let usable_register_clusters = blocks
@@ -66,13 +171,35 @@ 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 without_placeholder = remove_placeholder ( & r. name ) ;
175+ let mut fs_name = fieldset_name ( b. clone ( ) , without_placeholder. clone ( ) ) ;
176+
177+ let mut counter = 0 ;
178+ loop {
179+ if counter != 0 {
180+ let last = fs_name. last_mut ( ) . unwrap ( ) ;
181+ * last = format ! ( "{}_{}" , without_placeholder, counter) ;
182+ }
183+
184+ counter += 1 ;
185+
186+ if !used_fieldset_names. contains ( & fs_name) {
187+ break ;
188+ }
189+ }
190+
191+ used_fieldset_names. insert ( fs_name. clone ( ) ) ;
192+
193+ for ( _, full_name) in names ( r, |r| & r. name ) {
194+ let full_name: Vec < _ > = fieldset_name ( b. clone ( ) , full_name) ;
195+ inner_block_to_fieldset. insert ( full_name, fs_name. clone ( ) ) ;
196+ }
197+
198+ Some ( ( fs_name, r. deref ( ) , fields) )
70199 } ) ;
71200
72- for ( block_name, r, fields) in usable_register_clusters {
73- let mut fieldset_name = block_name. clone ( ) ;
201+ for ( fieldset_name, r, fields) in usable_register_clusters {
74202 let mut field_name_counts: BTreeMap < String , usize > = BTreeMap :: new ( ) ;
75- fieldset_name. push ( remove_placeholder ( & r. name ) ) ;
76203 fieldsets. push ( ProtoFieldset {
77204 name : fieldset_name. clone ( ) ,
78205 description : r. description . clone ( ) ,
@@ -90,7 +217,6 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
90217 let mut enum_readwrite = None ;
91218
92219 let mut field_name = remove_placeholder ( & f. name ) ;
93-
94220 let field_name_count = field_name_counts. entry ( field_name. clone ( ) ) . or_insert ( 0 ) ;
95221 * field_name_count += 1 ;
96222 if * field_name_count > 1 {
@@ -209,74 +335,66 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
209335 continue ;
210336 }
211337
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)
338+ let names = crate :: svd2ir:: names ( & r, |r| & r. name ) ;
339+ let array = names. array ( ) ;
340+
341+ for ( offset, name) in names {
342+ let fieldset_name = if r. fields . is_some ( ) {
343+ let fieldset_full_name =
344+ fieldset_name ( proto. name . clone ( ) , name. clone ( ) ) ;
345+ let fieldset_name =
346+ inner_block_to_fieldset. get ( & fieldset_full_name) . unwrap ( ) ;
347+ Some ( fieldset_names. get ( fieldset_name) . unwrap ( ) . clone ( ) )
348+ } else {
349+ None
350+ } ;
351+
352+ let access = match r. properties . access {
353+ None => Access :: ReadWrite ,
354+ Some ( svd:: Access :: ReadOnly ) => Access :: Read ,
355+ Some ( svd:: Access :: WriteOnly ) => Access :: Write ,
356+ Some ( svd:: Access :: WriteOnce ) => Access :: Write ,
357+ Some ( svd:: Access :: ReadWrite ) => Access :: ReadWrite ,
358+ Some ( svd:: Access :: ReadWriteOnce ) => Access :: ReadWrite ,
359+ } ;
360+
361+ let block_item = BlockItem {
362+ name : name,
363+ description : r. description . clone ( ) ,
364+ array : array. clone ( ) ,
365+ byte_offset : r. address_offset + offset,
366+ inner : BlockItemInner :: Register ( Register {
367+ access, // todo
368+ bit_size : r. properties . size . unwrap_or ( 32 ) ,
369+ fieldset : fieldset_name. clone ( ) ,
370+ } ) ,
371+ } ;
372+
373+ block. items . push ( block_item)
374+ }
251375 }
252376 svd:: RegisterCluster :: Cluster ( c) => {
253377 if c. derived_from . is_some ( ) {
254378 warn ! ( "unsupported derived_from in clusters" ) ;
255379 continue ;
256380 }
257381
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- } ) ;
382+ let names = names ( c, |c| & c. name ) ;
383+ let array = names. array ( ) ;
384+
385+ for ( offset, cname) in names {
386+ let mut block_name = proto. name . clone ( ) ;
387+ block_name. push ( cname. clone ( ) ) ;
388+ let block_name = block_names. get ( & block_name) . unwrap ( ) . clone ( ) ;
389+
390+ block. items . push ( BlockItem {
391+ name : cname. clone ( ) ,
392+ description : c. description . clone ( ) ,
393+ array : array. clone ( ) ,
394+ byte_offset : c. address_offset + offset,
395+ inner : BlockItemInner :: Block ( BlockItemBlock { block : block_name } ) ,
396+ } ) ;
397+ }
280398 }
281399 }
282400 }
@@ -299,37 +417,31 @@ pub fn convert_peripheral(ir: &mut IR, p: &svd::Peripheral) -> anyhow::Result<()
299417 warn ! ( "unsupported derived_from in fieldset" ) ;
300418 }
301419
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- } ;
420+ let names = names ( f, |f| & f. name ) ;
421+ let array = names. array ( ) ;
310422
311- let field_name = remove_placeholder ( & f. name ) ;
423+ for ( offset, field_name) in names {
424+ let mut field = Field {
425+ name : field_name. clone ( ) ,
426+ description : f. description . clone ( ) ,
427+ bit_offset : BitOffset :: Regular ( f. bit_range . offset + offset) ,
428+ bit_size : f. bit_range . width ,
429+ array : array. clone ( ) ,
430+ enumm : None ,
431+ } ;
312432
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- } ;
433+ if !f. enumerated_values . is_empty ( ) {
434+ let mut enum_name = proto. name . clone ( ) ;
435+ enum_name. push ( field_name) ;
321436
322- if !f. enumerated_values . is_empty ( ) {
323- let mut enum_name = proto. name . clone ( ) ;
324- enum_name. push ( field_name) ;
437+ trace ! ( "finding enum {:?}" , enum_name) ;
438+ let enum_name = enum_names. get ( & enum_name) . unwrap ( ) . clone ( ) ;
439+ trace ! ( "found {:?}" , enum_name) ;
440+ field. enumm = Some ( enum_name. clone ( ) )
441+ }
325442
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 ( ) )
443+ fieldset. fields . push ( field)
330444 }
331-
332- fieldset. fields . push ( field)
333445 }
334446
335447 let fieldset_name = fieldset_names. get ( & proto. name ) . unwrap ( ) . clone ( ) ;
@@ -492,9 +604,11 @@ fn collect_blocks(
492604 continue ;
493605 }
494606
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 ) ;
607+ for ( _, block) in names ( c, |c| & c. name ) {
608+ let mut block_name = block_name. clone ( ) ;
609+ block_name. push ( block) ;
610+ collect_blocks ( out, block_name, c. description . clone ( ) , & c. children ) ;
611+ }
498612 }
499613 }
500614}
@@ -588,7 +702,3 @@ pub fn namespace_names(peripheral: &PeripheralInfo, ir: &mut IR, namespace: Name
588702 }
589703 } ) ;
590704}
591-
592- pub fn remove_placeholder ( name : & str ) -> String {
593- name. replace ( "[%s]" , "" ) . replace ( "%s" , "" )
594- }
0 commit comments