@@ -228,23 +228,15 @@ pub fn fields(
228228 // TODO(AJM) - do we need to do anything with this range type?
229229 let BitRange { offset, width, .. } = f. bit_range ;
230230 let span = Span :: call_site ( ) ;
231- let sc = Ident :: new ( & f. name . to_sanitized_snake_case ( ) , span) ;
232- let pc = f. name . to_sanitized_upper_case ( ) ;
231+ let name = util:: replace_suffix ( & f. name , "" ) ;
232+ let sc = Ident :: new ( & name. to_sanitized_snake_case ( ) , span) ;
233+ let pc = name. to_sanitized_upper_case ( ) ;
233234 let bits = Ident :: new ( if width == 1 { "bit" } else { "bits" } , span) ;
234- let mut description_with_bits = if width == 1 {
235- format ! ( "Bit {}" , offset)
236- } else {
237- format ! ( "Bits {}:{}" , offset, offset + width - 1 )
238- } ;
239235 let description = if let Some ( d) = & f. description {
240236 util:: respace ( & util:: escape_brackets ( d) )
241237 } else {
242238 "" . to_owned ( )
243239 } ;
244- if !description. is_empty ( ) {
245- description_with_bits. push_str ( " - " ) ;
246- description_with_bits. push_str ( & description) ;
247- }
248240
249241 let can_read = [ Access :: ReadOnly , Access :: ReadWriteOnce , Access :: ReadWrite ]
250242 . contains ( & access)
@@ -275,6 +267,33 @@ pub fn fields(
275267
276268 let mut evs_r = None ;
277269
270+ let field_dim = match f {
271+ Field :: Array ( _, de) => {
272+ let ( first, index) = if let Some ( dim_index) = & de. dim_index {
273+ if let Ok ( first) = dim_index[ 0 ] . parse :: < u32 > ( ) {
274+ let sequential_indexes = dim_index
275+ . iter ( )
276+ . map ( |element| element. parse :: < u32 > ( ) )
277+ . eq ( ( first..de. dim + first) . map ( Ok ) ) ;
278+ if !sequential_indexes {
279+ return Err ( format ! ( "unsupported array indexes in {}" , f. name) ) ?;
280+ }
281+ ( first, None )
282+ } else {
283+ ( 0 , de. dim_index . clone ( ) )
284+ }
285+ } else {
286+ ( 0 , None )
287+ } ;
288+ let suffixes: Vec < _ > = match index {
289+ Some ( ix) => ix,
290+ None => ( 0 ..de. dim ) . map ( |i| ( first + i) . to_string ( ) ) . collect ( ) ,
291+ } ;
292+ Some ( ( first, de. dim , de. dim_increment , suffixes) )
293+ }
294+ Field :: Single ( _) => None ,
295+ } ;
296+
278297 if can_read {
279298 let _pc_r = Ident :: new ( & ( pc. clone ( ) + "_R" ) , span) ;
280299
@@ -294,20 +313,64 @@ pub fn fields(
294313 }
295314 } ;
296315
297- if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
298- evs_r = Some ( evs. clone ( ) ) ;
299-
316+ if let Some ( ( first, dim, increment, suffixes) ) = field_dim. clone ( ) {
317+ let offset_calc = calculate_offset ( first, increment, offset) ;
318+ let value = quote ! { ( ( self . bits >> #offset_calc) & #hexmask) #cast } ;
319+ let doc = & description;
320+ r_impl_items. push ( quote ! {
321+ #[ doc = #doc]
322+ #[ inline( always) ]
323+ pub unsafe fn #sc( & self , n: usize ) -> #_pc_r {
324+ #_pc_r:: new( #value )
325+ }
326+ } ) ;
327+ for ( i, suffix) in ( 0 ..dim) . zip ( suffixes. iter ( ) ) {
328+ let sub_offset = offset + ( i as u64 ) * ( increment as u64 ) ;
329+ let value = if sub_offset != 0 {
330+ let sub_offset = & util:: unsuffixed ( sub_offset) ;
331+ quote ! {
332+ ( ( self . bits >> #sub_offset) & #hexmask) #cast
333+ }
334+ } else {
335+ quote ! {
336+ ( self . bits & #hexmask) #cast
337+ }
338+ } ;
339+ let sc_n = Ident :: new (
340+ & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) , & suffix) ,
341+ Span :: call_site ( ) ,
342+ ) ;
343+ let doc = util:: replace_suffix (
344+ & description_with_bits ( & description, sub_offset, width) ,
345+ & suffix,
346+ ) ;
347+ r_impl_items. push ( quote ! {
348+ #[ doc = #doc]
349+ #[ inline( always) ]
350+ pub fn #sc_n( & self ) -> #_pc_r {
351+ #_pc_r:: new( #value )
352+ }
353+ } ) ;
354+ }
355+ } else {
356+ let doc = description_with_bits ( & description, offset, width) ;
300357 r_impl_items. push ( quote ! {
301- #[ doc = #description_with_bits ]
358+ #[ doc = #doc ]
302359 #[ inline( always) ]
303360 pub fn #sc( & self ) -> #_pc_r {
304361 #_pc_r:: new( #value )
305362 }
306363 } ) ;
364+ }
365+
366+ if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
367+ evs_r = Some ( evs. clone ( ) ) ;
307368
308369 if let Some ( base) = base {
309- let pc = base. field . to_sanitized_upper_case ( ) ;
310- let base_pc_r = Ident :: new ( & ( pc. clone ( ) + "_A" ) , span) ;
370+ let base_pc_r = Ident :: new (
371+ & ( util:: replace_suffix ( base. field , "" ) . to_sanitized_upper_case ( ) + "_A" ) ,
372+ span,
373+ ) ;
311374 derive_from_base ( mod_items, & base, & pc_r, & base_pc_r, & description) ;
312375
313376 let doc = format ! ( "Reader of field `{}`" , f. name) ;
@@ -403,14 +466,6 @@ pub fn fields(
403466 } ) ;
404467 }
405468 } else {
406- r_impl_items. push ( quote ! {
407- #[ doc = #description_with_bits]
408- #[ inline( always) ]
409- pub fn #sc( & self ) -> #_pc_r {
410- #_pc_r:: new ( #value )
411- }
412- } ) ;
413-
414469 let doc = format ! ( "Reader of field `{}`" , f. name) ;
415470 mod_items. push ( quote ! {
416471 #[ doc = #doc]
@@ -436,8 +491,11 @@ pub fn fields(
436491 if Some ( evs) != evs_r. as_ref ( ) {
437492 pc_w = & new_pc_w;
438493 if let Some ( base) = base {
439- let pc = base. field . to_sanitized_upper_case ( ) ;
440- let base_pc_w = Ident :: new ( & ( pc + "_AW" ) , span) ;
494+ let base_pc_w = Ident :: new (
495+ & ( util:: replace_suffix ( base. field , "" ) . to_sanitized_upper_case ( )
496+ + "_AW" ) ,
497+ span,
498+ ) ;
441499 derive_from_base ( mod_items, & base, & pc_w, & base_pc_w, & description)
442500 } else {
443501 add_from_variants ( mod_items, & variants, pc_w, & fty, & description, rv) ;
@@ -485,7 +543,16 @@ pub fn fields(
485543 } ) ;
486544 }
487545
488- proxy_items. push ( if offset != 0 {
546+ proxy_items. push ( if field_dim. is_some ( ) {
547+ quote ! {
548+ ///Writes raw bits to the field
549+ #[ inline( always) ]
550+ pub #unsafety fn #bits( self , value: #fty) -> & ' a mut W {
551+ self . w. bits = ( self . w. bits & !( #hexmask << self . offset) ) | ( ( ( value as #rty) & #hexmask) << self . offset) ;
552+ self . w
553+ }
554+ }
555+ } else if offset != 0 {
489556 let offset = & util:: unsuffixed ( offset) ;
490557 quote ! {
491558 ///Writes raw bits to the field
@@ -506,25 +573,64 @@ pub fn fields(
506573 }
507574 } ) ;
508575
576+ let offset_entry = if field_dim. is_some ( ) {
577+ quote ! { offset: usize , }
578+ } else {
579+ quote ! { }
580+ } ;
581+
509582 let doc = format ! ( "Write proxy for field `{}`" , f. name) ;
510583 mod_items. push ( quote ! {
511584 #[ doc = #doc]
512585 pub struct #_pc_w<' a> {
513586 w: & ' a mut W ,
587+ #offset_entry
514588 }
515589
516590 impl <' a> #_pc_w<' a> {
517591 #( #proxy_items) *
518592 }
519593 } ) ;
520594
521- w_impl_items. push ( quote ! {
522- #[ doc = #description_with_bits]
523- #[ inline( always) ]
524- pub fn #sc( & mut self ) -> #_pc_w {
525- #_pc_w { w: self }
595+ if let Some ( ( first, dim, increment, suffixes) ) = field_dim. clone ( ) {
596+ let offset_calc = calculate_offset ( first, increment, offset) ;
597+ let doc = & f. description ;
598+ w_impl_items. push ( quote ! {
599+ #[ doc = #doc]
600+ #[ inline( always) ]
601+ pub unsafe fn #sc( & mut self , n: usize ) -> #_pc_w {
602+ #_pc_w { w: self , offset: #offset_calc }
603+ }
604+ } ) ;
605+ for ( i, suffix) in ( 0 ..dim) . zip ( suffixes. iter ( ) ) {
606+ let sub_offset = offset + ( i as u64 ) * ( increment as u64 ) ;
607+ let sc_n = Ident :: new (
608+ & util:: replace_suffix ( & f. name . to_sanitized_snake_case ( ) , & suffix) ,
609+ Span :: call_site ( ) ,
610+ ) ;
611+ let doc = util:: replace_suffix (
612+ & description_with_bits ( & description, sub_offset, width) ,
613+ & suffix,
614+ ) ;
615+ let sub_offset = util:: unsuffixed ( sub_offset as u64 ) ;
616+ w_impl_items. push ( quote ! {
617+ #[ doc = #doc]
618+ #[ inline( always) ]
619+ pub fn #sc_n( & mut self ) -> #_pc_w {
620+ #_pc_w { w: self , offset: #sub_offset }
621+ }
622+ } ) ;
526623 }
527- } )
624+ } else {
625+ let doc = description_with_bits ( & description, offset, width) ;
626+ w_impl_items. push ( quote ! {
627+ #[ doc = #doc]
628+ #[ inline( always) ]
629+ pub fn #sc( & mut self ) -> #_pc_w {
630+ #_pc_w { w: self }
631+ }
632+ } ) ;
633+ }
528634 }
529635 }
530636
@@ -634,6 +740,41 @@ fn add_from_variants(
634740 } ) ;
635741}
636742
743+ fn calculate_offset ( first : u32 , increment : u32 , offset : u64 ) -> TokenStream {
744+ let mut res = if first != 0 {
745+ let first = util:: unsuffixed ( first as u64 ) ;
746+ quote ! { n - #first }
747+ } else {
748+ quote ! { n }
749+ } ;
750+ if increment != 1 {
751+ let increment = util:: unsuffixed ( increment as u64 ) ;
752+ res = if first != 0 {
753+ quote ! { ( #res) * #increment }
754+ } else {
755+ quote ! { #res * #increment }
756+ } ;
757+ }
758+ if offset != 0 {
759+ let offset = & util:: unsuffixed ( offset) ;
760+ res = quote ! { #res + #offset } ;
761+ }
762+ res
763+ }
764+
765+ fn description_with_bits ( description : & str , offset : u64 , width : u32 ) -> String {
766+ let mut res = if width == 1 {
767+ format ! ( "Bit {}" , offset)
768+ } else {
769+ format ! ( "Bits {}:{}" , offset, offset + width as u64 - 1 )
770+ } ;
771+ if description. len ( ) > 0 {
772+ res. push_str ( " - " ) ;
773+ res. push_str ( & util:: respace ( & util:: escape_brackets ( description) ) ) ;
774+ }
775+ res
776+ }
777+
637778fn derive_from_base (
638779 mod_items : & mut Vec < TokenStream > ,
639780 base : & Base ,
0 commit comments