@@ -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+ #inline
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+ #inline
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+ #inline
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+ #inline
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+ #inline
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+ #inline
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+ #inline
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+ #inline
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