@@ -213,26 +213,19 @@ pub fn fields(
213213    let  can_write = access != Access :: ReadOnly ; 
214214
215215    // TODO enumeratedValues 
216+     let  inline = quote !  {  #[ inline( always) ]  } ; 
216217    for  f in  fields. iter ( )  { 
217218        // TODO(AJM) - do we need to do anything with this range type? 
218219        let  BitRange  {  offset,  width,  .. }  = f. bit_range ; 
219-         let  sc = Ident :: new ( & f. name . to_sanitized_snake_case ( ) ,  span) ; 
220-         let  pc = f. name . to_sanitized_upper_case ( ) ; 
220+         let  name = util:: replace_suffix ( & f. name ,  "" ) ; 
221+         let  sc = Ident :: new ( & name. to_sanitized_snake_case ( ) ,  span) ; 
222+         let  pc = name. to_sanitized_upper_case ( ) ; 
221223        let  bits = Ident :: new ( if  width == 1  {  "bit"  }  else  {  "bits"  } ,  span) ; 
222-         let  mut  description_with_bits = if  width == 1  { 
223-             format ! ( "Bit {}" ,  offset) 
224-         }  else  { 
225-             format ! ( "Bits {}:{}" ,  offset,  offset + width - 1 ) 
226-         } ; 
227224        let  description = if  let  Some ( d)  = & f. description  { 
228225            util:: respace ( & util:: escape_brackets ( d) ) 
229226        }  else  { 
230227            "" . to_owned ( ) 
231228        } ; 
232-         if  !description. is_empty ( )  { 
233-             description_with_bits. push_str ( " - " ) ; 
234-             description_with_bits. push_str ( & description) ; 
235-         } 
236229
237230        let  can_read = can_read
238231            && ( f. access  != Some ( Access :: WriteOnly ) ) 
@@ -245,8 +238,6 @@ pub fn fields(
245238        let  rv = reset_value. map ( |rv| ( rv >> offset)  &  mask) ; 
246239        let  fty = width. to_ty ( ) ?; 
247240        let  evs = & f. enumerated_values ; 
248-         let  quotedfield = String :: from ( "`" )  + & f. name  + "`" ; 
249-         let  readerdoc = String :: from ( "Reader of field " )  + & quotedfield; 
250241
251242        let  lookup_results = lookup ( 
252243            evs, 
@@ -264,7 +255,50 @@ pub fn fields(
264255
265256        let  mut  evs_r = None ; 
266257
258+         let  field_dim = match  f { 
259+             Field :: Array ( _,  de)  => { 
260+                 let  ( first,  index)  = if  let  Some ( dim_index)  = & de. dim_index  { 
261+                     if  let  Ok ( first)  = dim_index[ 0 ] . parse :: < u32 > ( )  { 
262+                         let  sequential_indexes = dim_index
263+                             . iter ( ) 
264+                             . map ( |element| element. parse :: < u32 > ( ) ) 
265+                             . eq ( ( first..de. dim  + first) . map ( Ok ) ) ; 
266+                         if  !sequential_indexes { 
267+                             return  Err ( format ! ( "unsupported array indexes in {}" ,  f. name) ) ?; 
268+                         } 
269+                         ( first,  None ) 
270+                     }  else  { 
271+                         ( 0 ,  de. dim_index . clone ( ) ) 
272+                     } 
273+                 }  else  { 
274+                     ( 0 ,  None ) 
275+                 } ; 
276+                 let  suffixes:  Vec < _ >  = match  index { 
277+                     Some ( ix)  => ix, 
278+                     None  => ( 0 ..de. dim ) . map ( |i| ( first + i) . to_string ( ) ) . collect ( ) , 
279+                 } ; 
280+                 let  suffixes_str = format ! ( "({}-{})" ,  first,  first + de. dim - 1 ) ; 
281+                 Some ( ( first,  de. dim ,  de. dim_increment ,  suffixes,  suffixes_str) ) 
282+             } 
283+             Field :: Single ( _)  => { 
284+                 if  f. name . contains ( "%s" )  { 
285+                     return  Err ( format ! ( "incorrect field {}" ,  f. name) ) ?; 
286+                 } 
287+                 None 
288+             } 
289+         } ; 
290+ 
267291        if  can_read { 
292+             let  readerdoc = if  let  Some ( ( _,  _,  _,  _,  suffixes_str) )  = & field_dim { 
293+                 format ! ( 
294+                     "Reader of fields `{}`" , 
295+                     util:: replace_suffix( & f. name,  suffixes_str) 
296+                 ) 
297+             }  else  { 
298+                 let  quotedfield = String :: from ( "`" )  + & f. name  + "`" ; 
299+                 String :: from ( "Reader of field " )  + & quotedfield
300+             } ; 
301+ 
268302            let  _pc_r = Ident :: new ( & ( pc. clone ( )  + "_R" ) ,  span) ; 
269303
270304            let  cast = if  width == 1  { 
@@ -283,20 +317,63 @@ pub fn fields(
283317                } 
284318            } ; 
285319
286-             r_impl_items. extend ( quote !  { 
287-                 #[ doc = #description_with_bits] 
288-                 #[ inline( always) ] 
289-                 pub  fn  #sc( & self )  -> #_pc_r { 
290-                     #_pc_r:: new (  #value ) 
320+             if  let  Some ( ( first,  dim,  increment,  suffixes,  suffixes_str) )  = & field_dim { 
321+                 let  offset_calc = calculate_offset ( * first,  * increment,  offset) ; 
322+                 let  value = quote !  {  ( ( self . bits >> #offset_calc)  &  #hexmask)  #cast } ; 
323+                 let  doc = & util:: replace_suffix ( & description,  suffixes_str) ; 
324+                 r_impl_items. extend ( quote !  { 
325+                     #[ doc = #doc] 
326+                     #inline
327+                     pub  unsafe  fn  #sc( & self ,  n:  usize )  -> #_pc_r { 
328+                         #_pc_r:: new (  #value ) 
329+                     } 
330+                 } ) ; 
331+                 for  ( i,  suffix)  in  ( 0 ..* dim) . zip ( suffixes. iter ( ) )  { 
332+                     let  sub_offset = offset + ( i as  u64 )  *  ( * increment as  u64 ) ; 
333+                     let  value = if  sub_offset != 0  { 
334+                         let  sub_offset = & util:: unsuffixed ( sub_offset) ; 
335+                         quote !  { 
336+                             ( ( self . bits >> #sub_offset)  &  #hexmask)  #cast
337+                         } 
338+                     }  else  { 
339+                         quote !  { 
340+                             ( self . bits &  #hexmask)  #cast
341+                         } 
342+                     } ; 
343+                     let  sc_n = Ident :: new ( 
344+                         & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) ,  & suffix) , 
345+                         Span :: call_site ( ) , 
346+                     ) ; 
347+                     let  doc = util:: replace_suffix ( 
348+                         & description_with_bits ( & description,  sub_offset,  width) , 
349+                         & suffix, 
350+                     ) ; 
351+                     r_impl_items. extend ( quote !  { 
352+                         #[ doc = #doc] 
353+                         #inline
354+                         pub  fn  #sc_n( & self )  -> #_pc_r { 
355+                             #_pc_r:: new (  #value ) 
356+                         } 
357+                     } ) ; 
291358                } 
292-             } ) ; 
359+             }  else  { 
360+                 let  doc = description_with_bits ( & description,  offset,  width) ; 
361+                 r_impl_items. extend ( quote !  { 
362+                     #[ doc = #doc] 
363+                     #inline
364+                     pub  fn  #sc( & self )  -> #_pc_r { 
365+                         #_pc_r:: new (  #value ) 
366+                     } 
367+                 } ) ; 
368+             } 
293369
294370            if  let  Some ( ( evs,  base) )  = lookup_filter ( & lookup_results,  Usage :: Read )  { 
295371                evs_r = Some ( evs. clone ( ) ) ; 
296372
297373                if  let  Some ( base)  = base { 
298-                     let  pc = base. field . to_sanitized_upper_case ( ) ; 
299-                     let  base_pc_r = Ident :: new ( & ( pc. clone ( )  + "_A" ) ,  span) ; 
374+                     let  pc = util:: replace_suffix ( base. field ,  "" ) ; 
375+                     let  pc = pc. to_sanitized_upper_case ( ) ; 
376+                     let  base_pc_r = Ident :: new ( & ( pc + "_A" ) ,  span) ; 
300377                    derive_from_base ( mod_items,  & base,  & pc_r,  & base_pc_r,  & description) ; 
301378
302379                    mod_items. extend ( quote !  { 
@@ -338,7 +415,7 @@ pub fn fields(
338415                    if  has_reserved_variant { 
339416                        enum_items. extend ( quote !  { 
340417                            ///Get enumerated values variant 
341- [ inline( always ) ] 
418+ 
342419                            pub  fn  variant( & self )  -> crate :: Variant <#fty,  #pc_r> { 
343420                                use  crate :: Variant :: * ; 
344421                                match  self . bits { 
@@ -349,7 +426,7 @@ pub fn fields(
349426                    }  else  { 
350427                        enum_items. extend ( quote !  { 
351428                            ///Get enumerated values variant 
352- [ inline( always ) ] 
429+ 
353430                            pub  fn  variant( & self )  -> #pc_r { 
354431                                match  self . bits { 
355432                                    #arms
@@ -374,7 +451,7 @@ pub fn fields(
374451                        let  doc = format ! ( "Checks if the value of the field is `{}`" ,  pc) ; 
375452                        enum_items. extend ( quote !  { 
376453                            #[ doc = #doc] 
377-                             #[ inline( always ) ] 
454+                             #inline
378455                            pub  fn  #is_variant( & self )  -> bool  { 
379456                                * self  == #pc_r:: #pc
380457                            } 
@@ -414,7 +491,8 @@ pub fn fields(
414491                if  Some ( evs)  != evs_r. as_ref ( )  { 
415492                    pc_w = & new_pc_w; 
416493                    if  let  Some ( base)  = base { 
417-                         let  pc = base. field . to_sanitized_upper_case ( ) ; 
494+                         let  pc = util:: replace_suffix ( base. field ,  "" ) ; 
495+                         let  pc = pc. to_sanitized_upper_case ( ) ; 
418496                        let  base_pc_w = Ident :: new ( & ( pc + "_AW" ) ,  span) ; 
419497                        derive_from_base ( mod_items,  & base,  & pc_w,  & base_pc_w,  & description) 
420498                    }  else  { 
@@ -424,7 +502,7 @@ pub fn fields(
424502
425503                proxy_items. extend ( quote !  { 
426504                    ///Writes `variant` to the field 
427- [ inline( always ) ] 
505+ 
428506                    pub  fn  variant( self ,  variant:  #pc_w)  -> & ' a mut  W  { 
429507                        #unsafety { 
430508                            self . #bits( variant. into( ) ) 
@@ -439,7 +517,7 @@ pub fn fields(
439517                    let  doc = util:: escape_brackets ( util:: respace ( & v. doc ) . as_ref ( ) ) ; 
440518                    proxy_items. extend ( quote !  { 
441519                        #[ doc = #doc] 
442-                         #[ inline( always ) ] 
520+                         #inline
443521                        pub  fn  #sc( self )  -> & ' a mut  W  { 
444522                            self . variant( #pc_w:: #pc) 
445523                        } 
@@ -450,24 +528,33 @@ pub fn fields(
450528            if  width == 1  { 
451529                proxy_items. extend ( quote !  { 
452530                    ///Sets the field bit 
453- [ inline( always ) ] 
531+ 
454532                    pub  #unsafety fn  set_bit( self )  -> & ' a mut  W  { 
455533                        self . bit( true ) 
456534                    } 
457535
458536                    ///Clears the field bit 
459- [ inline( always ) ] 
537+ 
460538                    pub  #unsafety fn  clear_bit( self )  -> & ' a mut  W  { 
461539                        self . bit( false ) 
462540                    } 
463541                } ) ; 
464542            } 
465543
466-             proxy_items. extend ( if  offset != 0  { 
544+             proxy_items. extend ( if  field_dim. is_some ( )  { 
545+                 quote !  { 
546+                     ///Writes raw bits to the field 
547+ 
548+                     pub  #unsafety fn  #bits( self ,  value:  #fty)  -> & ' a mut  W  { 
549+                         self . w. bits = ( self . w. bits &  !( #hexmask << self . offset) )  | ( ( ( value as  #rty)  &  #hexmask)  << self . offset) ; 
550+                         self . w
551+                     } 
552+                 } 
553+             }  else  if  offset != 0  { 
467554                let  offset = & util:: unsuffixed ( offset) ; 
468555                quote !  { 
469556                    ///Writes raw bits to the field 
470- [ inline( always ) ] 
557+ 
471558                    pub  #unsafety fn  #bits( self ,  value:  #fty)  -> & ' a mut  W  { 
472559                        self . w. bits = ( self . w. bits &  !( #hexmask << #offset) )  | ( ( ( value as  #rty)  &  #hexmask)  << #offset) ; 
473560                        self . w
@@ -476,33 +563,78 @@ pub fn fields(
476563            }  else  { 
477564                quote !  { 
478565                    ///Writes raw bits to the field 
479- [ inline( always ) ] 
566+ 
480567                    pub  #unsafety fn  #bits( self ,  value:  #fty)  -> & ' a mut  W  { 
481568                        self . w. bits = ( self . w. bits &  !#hexmask)  | ( ( value as  #rty)  &  #hexmask) ; 
482569                        self . w
483570                    } 
484571                } 
485572            } ) ; 
486573
487-             let  doc = format ! ( "Write proxy for field `{}`" ,  f. name) ; 
574+             let  doc; 
575+             let  offset_entry; 
576+             if  let  Some ( ( _,  _,  _,  _,  suffixes_str) )  = & field_dim { 
577+                 doc = format ! ( 
578+                     "Write proxy for fields `{}`" , 
579+                     util:: replace_suffix( & f. name,  suffixes_str) 
580+                 ) ; 
581+                 offset_entry = quote !  { offset:  usize , } ; 
582+             }  else  { 
583+                 doc = format ! ( "Write proxy for field `{}`" ,  f. name) ; 
584+                 offset_entry = quote !  { } ; 
585+             } 
586+ 
488587            mod_items. extend ( quote !  { 
489588                #[ doc = #doc] 
490589                pub  struct  #_pc_w<' a> { 
491590                    w:  & ' a mut  W , 
591+                     #offset_entry
492592                } 
493593
494594                impl <' a> #_pc_w<' a> { 
495595                    #proxy_items
496596                } 
497597            } ) ; 
498598
499-             w_impl_items. extend ( quote !  { 
500-                 #[ doc = #description_with_bits] 
501-                 #[ inline( always) ] 
502-                 pub  fn  #sc( & mut  self )  -> #_pc_w { 
503-                     #_pc_w {  w:  self  } 
599+             if  let  Some ( ( first,  dim,  increment,  suffixes,  suffixes_str) )  = & field_dim { 
600+                 let  offset_calc = calculate_offset ( * first,  * increment,  offset) ; 
601+                 let  doc = & util:: replace_suffix ( & description,  suffixes_str) ; 
602+                 w_impl_items. extend ( quote !  { 
603+                     #[ doc = #doc] 
604+                     #inline
605+                     pub  unsafe  fn  #sc( & mut  self ,  n:  usize )  -> #_pc_w { 
606+                         #_pc_w {  w:  self ,  offset:  #offset_calc } 
607+                     } 
608+                 } ) ; 
609+                 for  ( i,  suffix)  in  ( 0 ..* dim) . zip ( suffixes. iter ( ) )  { 
610+                     let  sub_offset = offset + ( i as  u64 )  *  ( * increment as  u64 ) ; 
611+                     let  sc_n = Ident :: new ( 
612+                         & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) ,  & suffix) , 
613+                         Span :: call_site ( ) , 
614+                     ) ; 
615+                     let  doc = util:: replace_suffix ( 
616+                         & description_with_bits ( & description,  sub_offset,  width) , 
617+                         & suffix, 
618+                     ) ; 
619+                     let  sub_offset = util:: unsuffixed ( sub_offset as  u64 ) ; 
620+                     w_impl_items. extend ( quote !  { 
621+                         #[ doc = #doc] 
622+                         #inline
623+                         pub  fn  #sc_n( & mut  self )  -> #_pc_w { 
624+                             #_pc_w {  w:  self ,  offset:  #sub_offset } 
625+                         } 
626+                     } ) ; 
504627                } 
505-             } ) 
628+             }  else  { 
629+                 let  doc = description_with_bits ( & description,  offset,  width) ; 
630+                 w_impl_items. extend ( quote !  { 
631+                     #[ doc = #doc] 
632+                     #inline
633+                     pub  fn  #sc( & mut  self )  -> #_pc_w { 
634+                         #_pc_w {  w:  self  } 
635+                     } 
636+                 } ) ; 
637+             } 
506638        } 
507639    } 
508640
@@ -612,6 +744,41 @@ fn add_from_variants(
612744    } ) ; 
613745} 
614746
747+ fn  calculate_offset ( first :  u32 ,  increment :  u32 ,  offset :  u64 )  -> TokenStream  { 
748+     let  mut  res = if  first != 0  { 
749+         let  first = util:: unsuffixed ( first as  u64 ) ; 
750+         quote !  {  n - #first } 
751+     }  else  { 
752+         quote !  {  n } 
753+     } ; 
754+     if  increment != 1  { 
755+         let  increment = util:: unsuffixed ( increment as  u64 ) ; 
756+         res = if  first != 0  { 
757+             quote !  {  ( #res)  *  #increment } 
758+         }  else  { 
759+             quote !  {  #res *  #increment } 
760+         } ; 
761+     } 
762+     if  offset != 0  { 
763+         let  offset = & util:: unsuffixed ( offset) ; 
764+         res = quote !  {  #res + #offset } ; 
765+     } 
766+     res
767+ } 
768+ 
769+ fn  description_with_bits ( description :  & str ,  offset :  u64 ,  width :  u32 )  -> String  { 
770+     let  mut  res = if  width == 1  { 
771+         format ! ( "Bit {}" ,  offset) 
772+     }  else  { 
773+         format ! ( "Bits {}:{}" ,  offset,  offset + width as  u64  - 1 ) 
774+     } ; 
775+     if  description. len ( )  > 0  { 
776+         res. push_str ( " - " ) ; 
777+         res. push_str ( & util:: respace ( & util:: escape_brackets ( description) ) ) ; 
778+     } 
779+     res
780+ } 
781+ 
615782fn  derive_from_base ( 
616783    mod_items :  & mut  TokenStream , 
617784    base :  & Base , 
0 commit comments