@@ -221,8 +221,9 @@ pub fn fields(
221221 width,
222222 range_type : _,
223223 } = f. bit_range ;
224- let sc = f. name . to_sanitized_snake_case ( ) ;
225- let pc = f. name . to_sanitized_upper_case ( ) ;
224+ let name = util:: replace_suffix ( & f. name , "" ) ;
225+ let sc = name. to_sanitized_snake_case ( ) ;
226+ let pc = name. to_sanitized_upper_case ( ) ;
226227 let span = Span :: call_site ( ) ;
227228 let pc_r = Ident :: new ( & format ! ( "{}_A" , pc) , span) ;
228229 let _pc_r = Ident :: new ( & format ! ( "{}_R" , pc) , span) ;
@@ -234,26 +235,44 @@ pub fn fields(
234235 } else {
235236 "bits"
236237 } , Span :: call_site ( ) ) ;
237- let mut description_with_bits = if width == 1 {
238- format ! ( "Bit {}" , offset)
239- } else {
240- format ! ( "Bits {}:{}" , offset, offset + width - 1 )
241- } ;
242- if let Some ( d) = & f. description {
243- description_with_bits. push_str ( " - " ) ;
244- description_with_bits. push_str ( & util:: respace ( & util:: escape_brackets ( d) ) ) ;
245- }
246238 let description = if let Some ( d) = & f. description {
247239 util:: respace ( & util:: escape_brackets ( d) )
248240 } else {
249241 "" . to_owned ( )
250242 } ;
251243
244+ let dim = match f {
245+ Field :: Array ( _, de) => {
246+ let ( first, index) = if let Some ( dim_index) = & de. dim_index {
247+ if let Ok ( first) = dim_index[ 0 ] . parse :: < u32 > ( ) {
248+ ( first, None )
249+ } else {
250+ ( 0 , de. dim_index . clone ( ) )
251+ }
252+ } else {
253+ ( 0 , None )
254+ } ;
255+ let span = Span :: call_site ( ) ;
256+ let names_with_index: Vec < _ > = match index {
257+ Some ( ix) => ix. iter ( ) . map ( |i| Ident :: new ( & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) , & i) , span) ) . collect ( ) ,
258+ None => ( 0 ..de. dim ) . map ( |i| Ident :: new ( & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) , & ( first + i) . to_string ( ) ) , span) ) . collect ( ) ,
259+ } ;
260+ let last = util:: unsuffixed ( ( first + de. dim - 1 ) as u64 ) ;
261+ let first_unsuf = util:: unsuffixed ( first as u64 ) ;
262+ let check = if first == 0 {
263+ quote ! { debug_assert!( n <= #last) ; }
264+ } else {
265+ quote ! { debug_assert!( n >= #first_unsuf && n <= #last) ; }
266+ } ;
267+ Some ( ( first, de. dim , de. dim_increment , check, names_with_index) )
268+ } ,
269+ Field :: Single ( _) => None
270+ } ;
271+
252272 Ok ( F {
253273 _pc_w,
254274 _sc,
255275 description,
256- description_with_bits,
257276 pc_r,
258277 _pc_r,
259278 pc_w,
@@ -267,6 +286,7 @@ pub fn fields(
267286 offset : u64:: from ( offset) ,
268287 ty : width. to_ty ( ) ?,
269288 write_constraint : f. write_constraint . as_ref ( ) ,
289+ dim,
270290 } )
271291 }
272292 }
@@ -306,10 +326,10 @@ pub fn fields(
306326 let _pc_r = & f. _pc_r ;
307327 let _pc_w = & f. _pc_w ;
308328 let description = & f. description ;
309- let description_with_bits = & f . description_with_bits ;
329+ let width = f . width ;
310330
311331 if can_read {
312- let cast = if f . width == 1 {
332+ let cast = if width == 1 {
313333 quote ! { != 0 }
314334 } else {
315335 quote ! { as #fty }
@@ -325,21 +345,59 @@ pub fn fields(
325345 }
326346 } ;
327347
328- if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
329- evs_r = Some ( evs. clone ( ) ) ;
330-
331- let sc = & f. sc ;
348+ let sc = & f. sc ;
349+ if let Some ( ( first, dim, increment, check, names) ) = f. dim . clone ( ) {
350+ let first_unsuf = util:: unsuffixed ( first as u64 ) ;
351+ let offset_unsuf = & util:: unsuffixed ( offset) ;
352+ let increment_unsuf = & util:: unsuffixed ( increment as u64 ) ;
353+ let offset_calc = quote ! { crate :: field_offset( n, #offset_unsuf, #first_unsuf, #increment_unsuf) } ;
354+ let value = quote ! { ( ( self . bits >> #offset_calc) & #mask) #cast } ;
355+ let doc = & f. description ;
356+ r_impl_items. push ( quote ! {
357+ #[ doc = #doc]
358+ #[ inline( always) ]
359+ pub fn #sc( & self , n: u32 ) -> #_pc_r {
360+ #check
361+ #_pc_r:: new( #value )
362+ }
363+ } ) ;
364+ for ( i, sc_n) in ( 0 ..dim) . zip ( names. iter ( ) ) {
365+ let offset = offset + ( i as u64 ) * ( increment as u64 ) ;
366+ let value = if offset != 0 {
367+ let offset = & util:: unsuffixed ( offset) ;
368+ quote ! {
369+ ( ( self . bits >> #offset) & #mask) #cast
370+ }
371+ } else {
372+ quote ! {
373+ ( self . bits & #mask) #cast
374+ }
375+ } ;
376+ let doc = description_with_bits ( & f. description , offset, width) ;
377+ r_impl_items. push ( quote ! {
378+ #[ doc = #doc]
379+ #[ inline( always) ]
380+ pub fn #sc_n( & self ) -> #_pc_r {
381+ #_pc_r:: new( #value )
382+ }
383+ } ) ;
384+ }
385+ } else {
386+ let doc = description_with_bits ( & f. description , f. offset , width) ;
332387 r_impl_items. push ( quote ! {
333- #[ doc = #description_with_bits ]
388+ #[ doc = #doc ]
334389 #[ inline( always) ]
335390 pub fn #sc( & self ) -> #_pc_r {
336391 #_pc_r:: new( #value )
337392 }
338393 } ) ;
394+ }
395+
396+ if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
397+ evs_r = Some ( evs. clone ( ) ) ;
339398
340399 base_pc_w = base. as_ref ( ) . map ( |base| {
341- let pc = base. field . to_sanitized_upper_case ( ) ;
342- let base_pc_r = Ident :: new ( & format ! ( "{}_A" , pc) , Span :: call_site ( ) ) ;
400+ let base_pc_r = Ident :: new ( & format ! ( "{}_A" , util:: replace_suffix( base. field, "" ) . to_sanitized_upper_case( ) ) , Span :: call_site ( ) ) ;
343401 let base_pc_r = derive_from_base ( mod_items, & base, & pc_r, & base_pc_r, description) ;
344402
345403 let doc = format ! ( "Reader of field `{}`" , f. name) ;
@@ -352,7 +410,7 @@ pub fn fields(
352410 } ) ;
353411
354412 if base. is_none ( ) {
355- let has_reserved_variant = evs. values . len ( ) != ( 1 << f . width ) ;
413+ let has_reserved_variant = evs. values . len ( ) != ( 1 << width) ;
356414 let variants = Variant :: from_enumerated_values ( evs) ?;
357415
358416 add_from_variants ( mod_items, & variants, pc_r, & f, description, rv) ;
@@ -362,7 +420,7 @@ pub fn fields(
362420 let mut arms = variants
363421 . iter ( )
364422 . map ( |v| {
365- let i = util:: unsuffixed_or_bool ( v. value , f . width ) ;
423+ let i = util:: unsuffixed_or_bool ( v. value , width) ;
366424 let pc = & v. pc ;
367425
368426 if has_reserved_variant {
@@ -377,7 +435,7 @@ pub fn fields(
377435 arms. push ( quote ! {
378436 i => Res ( i)
379437 } ) ;
380- } else if 1 << f . width . to_ty_width ( ) ? != variants. len ( ) {
438+ } else if 1 << width. to_ty_width ( ) ? != variants. len ( ) {
381439 arms. push ( quote ! {
382440 _ => unreachable!( )
383441 } ) ;
@@ -437,15 +495,6 @@ pub fn fields(
437495 }
438496
439497 } else {
440- let sc = & f. sc ;
441- r_impl_items. push ( quote ! {
442- #[ doc = #description_with_bits]
443- #[ inline( always) ]
444- pub fn #sc( & self ) -> #_pc_r {
445- #_pc_r:: new ( #value )
446- }
447- } ) ;
448-
449498 let doc = format ! ( "Reader of field `{}`" , f. name) ;
450499 mod_items. push ( quote ! {
451500 #[ doc = #doc]
@@ -458,22 +507,20 @@ pub fn fields(
458507 if can_write {
459508 let mut proxy_items = vec ! [ ] ;
460509
461- let mut unsafety = unsafety ( f. write_constraint , f. width ) ;
462- let width = f. width ;
510+ let mut unsafety = unsafety ( f. write_constraint , width) ;
463511
464512 if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Write ) {
465513 let variants = Variant :: from_enumerated_values ( evs) ?;
466514
467- if variants. len ( ) == 1 << f . width {
515+ if variants. len ( ) == 1 << width {
468516 unsafety = None ;
469517 }
470518
471519 if Some ( evs) != evs_r. as_ref ( ) {
472520 pc_w = & f. pc_w ;
473521
474522 base_pc_w = base. as_ref ( ) . map ( |base| {
475- let pc = base. field . to_sanitized_upper_case ( ) ;
476- let base_pc_w = Ident :: new ( & format ! ( "{}_AW" , pc) , Span :: call_site ( ) ) ;
523+ let base_pc_w = Ident :: new ( & format ! ( "{}_AW" , util:: replace_suffix( base. field, "" ) . to_sanitized_upper_case( ) ) , Span :: call_site ( ) ) ;
477524 derive_from_base ( mod_items, & base, & pc_w, & base_pc_w, description)
478525 } ) ;
479526
@@ -533,7 +580,20 @@ pub fn fields(
533580 } ) ;
534581 }
535582
536- proxy_items. push ( if offset != 0 {
583+ proxy_items. push ( if let Some ( ( first, _, increment, _, _) ) = f. dim {
584+ let offset = & util:: unsuffixed ( offset) ;
585+ let first = util:: unsuffixed ( first as u64 ) ;
586+ let increment_unsuf = util:: unsuffixed ( increment as u64 ) ;
587+ let offset_calc = quote ! { crate :: field_offset( self . n, #offset, #first, #increment_unsuf) } ;
588+ quote ! {
589+ ///Writes raw bits to the field
590+ #[ inline( always) ]
591+ pub #unsafety fn #bits( self , value: #fty) -> & ' a mut W {
592+ self . w. bits = ( self . w. bits & !( #mask << #offset_calc) ) | ( ( ( value as #rty) & #mask) << #offset_calc) ;
593+ self . w
594+ }
595+ }
596+ } else if offset != 0 {
537597 let offset = & util:: unsuffixed ( offset) ;
538598 quote ! {
539599 ///Writes raw bits to the field
@@ -554,11 +614,18 @@ pub fn fields(
554614 }
555615 } ) ;
556616
617+ let n_entry = if f. dim . is_some ( ) {
618+ quote ! { n: u32 , }
619+ } else {
620+ quote ! { }
621+ } ;
622+
557623 let doc = format ! ( "Write proxy for field `{}`" , f. name) ;
558624 mod_items. push ( quote ! {
559625 #[ doc = #doc]
560626 pub struct #_pc_w<' a> {
561627 w: & ' a mut W ,
628+ #n_entry
562629 }
563630
564631 impl <' a> #_pc_w<' a> {
@@ -567,13 +634,39 @@ pub fn fields(
567634 } ) ;
568635
569636 let sc = & f. sc ;
570- w_impl_items. push ( quote ! {
571- #[ doc = #description_with_bits]
572- #[ inline( always) ]
573- pub fn #sc( & mut self ) -> #_pc_w {
574- #_pc_w { w: self }
637+ if let Some ( ( first, dim, increment, check, names) ) = f. dim . clone ( ) {
638+ let doc = & f. description ;
639+ w_impl_items. push ( quote ! {
640+ #[ doc = #doc]
641+ #[ inline( always) ]
642+ pub fn #sc( & mut self , n: u32 ) -> #_pc_w {
643+ #check
644+ #_pc_w { w: self , n }
645+ }
646+ } ) ;
647+ for ( i, sc_n) in ( 0 ..dim) . zip ( names. iter ( ) ) {
648+ let n = first + i;
649+ let n = util:: unsuffixed ( n as u64 ) ;
650+ let offset = offset + ( i as u64 ) * ( increment as u64 ) ;
651+ let doc = description_with_bits ( & f. description , offset, width) ;
652+ w_impl_items. push ( quote ! {
653+ #[ doc = #doc]
654+ #[ inline( always) ]
655+ pub fn #sc_n( & mut self ) -> #_pc_w {
656+ #_pc_w { w: self , n: #n }
657+ }
658+ } ) ;
575659 }
576- } )
660+ } else {
661+ let doc = description_with_bits ( & f. description , f. offset , width) ;
662+ w_impl_items. push ( quote ! {
663+ #[ doc = #doc]
664+ #[ inline( always) ]
665+ pub fn #sc( & mut self ) -> #_pc_w {
666+ #_pc_w { w: self }
667+ }
668+ } ) ;
669+ }
577670 }
578671 }
579672
@@ -719,12 +812,24 @@ fn derive_from_base(mod_items: &mut Vec<TokenStream>, base: &Base, pc: &Ident, b
719812 }
720813}
721814
815+ fn description_with_bits ( description : & str , offset : u64 , width : u32 ) -> String {
816+ let mut res = if width == 1 {
817+ format ! ( "Bit {}" , offset)
818+ } else {
819+ format ! ( "Bits {}:{}" , offset, offset + width as u64 - 1 )
820+ } ;
821+ if description. len ( ) > 0 {
822+ res. push_str ( " - " ) ;
823+ res. push_str ( & util:: respace ( & util:: escape_brackets ( description) ) ) ;
824+ }
825+ res
826+ }
827+
722828struct F < ' a > {
723829 _pc_w : Ident ,
724830 _sc : Ident ,
725831 access : Option < Access > ,
726832 description : String ,
727- description_with_bits : String ,
728833 evs : & ' a [ EnumeratedValues ] ,
729834 mask : u64 ,
730835 name : & ' a str ,
@@ -737,6 +842,7 @@ struct F<'a> {
737842 ty : Ident ,
738843 width : u32 ,
739844 write_constraint : Option < & ' a WriteConstraint > ,
845+ dim : Option < ( u32 , u32 , u32 , TokenStream , Vec < Ident > ) > ,
740846}
741847
742848#[ derive( Clone , Debug ) ]
0 commit comments