@@ -213,26 +213,19 @@ pub fn fields(
213
213
let can_write = access != Access :: ReadOnly ;
214
214
215
215
// TODO enumeratedValues
216
+ let inline = quote ! { #[ inline( always) ] } ;
216
217
for f in fields. iter ( ) {
217
218
// TODO(AJM) - do we need to do anything with this range type?
218
219
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 ( ) ;
221
223
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
- } ;
227
224
let description = if let Some ( d) = & f. description {
228
225
util:: respace ( & util:: escape_brackets ( d) )
229
226
} else {
230
227
"" . to_owned ( )
231
228
} ;
232
- if !description. is_empty ( ) {
233
- description_with_bits. push_str ( " - " ) ;
234
- description_with_bits. push_str ( & description) ;
235
- }
236
229
237
230
let can_read = can_read
238
231
&& ( f. access != Some ( Access :: WriteOnly ) )
@@ -245,8 +238,6 @@ pub fn fields(
245
238
let rv = reset_value. map ( |rv| ( rv >> offset) & mask) ;
246
239
let fty = width. to_ty ( ) ?;
247
240
let evs = & f. enumerated_values ;
248
- let quotedfield = String :: from ( "`" ) + & f. name + "`" ;
249
- let readerdoc = String :: from ( "Reader of field " ) + & quotedfield;
250
241
251
242
let lookup_results = lookup (
252
243
evs,
@@ -264,7 +255,50 @@ pub fn fields(
264
255
265
256
let mut evs_r = None ;
266
257
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
+
267
291
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
+
268
302
let _pc_r = Ident :: new ( & ( pc. clone ( ) + "_R" ) , span) ;
269
303
270
304
let cast = if width == 1 {
@@ -283,20 +317,63 @@ pub fn fields(
283
317
}
284
318
} ;
285
319
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
+ } ) ;
291
358
}
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
+ }
293
369
294
370
if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
295
371
evs_r = Some ( evs. clone ( ) ) ;
296
372
297
373
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) ;
300
377
derive_from_base ( mod_items, & base, & pc_r, & base_pc_r, & description) ;
301
378
302
379
mod_items. extend ( quote ! {
@@ -338,7 +415,7 @@ pub fn fields(
338
415
if has_reserved_variant {
339
416
enum_items. extend ( quote ! {
340
417
///Get enumerated values variant
341
- #[ inline( always ) ]
418
+ #inline
342
419
pub fn variant( & self ) -> crate :: Variant <#fty, #pc_r> {
343
420
use crate :: Variant :: * ;
344
421
match self . bits {
@@ -349,7 +426,7 @@ pub fn fields(
349
426
} else {
350
427
enum_items. extend ( quote ! {
351
428
///Get enumerated values variant
352
- #[ inline( always ) ]
429
+ #inline
353
430
pub fn variant( & self ) -> #pc_r {
354
431
match self . bits {
355
432
#arms
@@ -374,7 +451,7 @@ pub fn fields(
374
451
let doc = format ! ( "Checks if the value of the field is `{}`" , pc) ;
375
452
enum_items. extend ( quote ! {
376
453
#[ doc = #doc]
377
- #[ inline( always ) ]
454
+ #inline
378
455
pub fn #is_variant( & self ) -> bool {
379
456
* self == #pc_r:: #pc
380
457
}
@@ -414,7 +491,8 @@ pub fn fields(
414
491
if Some ( evs) != evs_r. as_ref ( ) {
415
492
pc_w = & new_pc_w;
416
493
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 ( ) ;
418
496
let base_pc_w = Ident :: new ( & ( pc + "_AW" ) , span) ;
419
497
derive_from_base ( mod_items, & base, & pc_w, & base_pc_w, & description)
420
498
} else {
@@ -424,7 +502,7 @@ pub fn fields(
424
502
425
503
proxy_items. extend ( quote ! {
426
504
///Writes `variant` to the field
427
- #[ inline( always ) ]
505
+ #inline
428
506
pub fn variant( self , variant: #pc_w) -> & ' a mut W {
429
507
#unsafety {
430
508
self . #bits( variant. into( ) )
@@ -439,7 +517,7 @@ pub fn fields(
439
517
let doc = util:: escape_brackets ( util:: respace ( & v. doc ) . as_ref ( ) ) ;
440
518
proxy_items. extend ( quote ! {
441
519
#[ doc = #doc]
442
- #[ inline( always ) ]
520
+ #inline
443
521
pub fn #sc( self ) -> & ' a mut W {
444
522
self . variant( #pc_w:: #pc)
445
523
}
@@ -450,24 +528,33 @@ pub fn fields(
450
528
if width == 1 {
451
529
proxy_items. extend ( quote ! {
452
530
///Sets the field bit
453
- #[ inline( always ) ]
531
+ #inline
454
532
pub #unsafety fn set_bit( self ) -> & ' a mut W {
455
533
self . bit( true )
456
534
}
457
535
458
536
///Clears the field bit
459
- #[ inline( always ) ]
537
+ #inline
460
538
pub #unsafety fn clear_bit( self ) -> & ' a mut W {
461
539
self . bit( false )
462
540
}
463
541
} ) ;
464
542
}
465
543
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 {
467
554
let offset = & util:: unsuffixed ( offset) ;
468
555
quote ! {
469
556
///Writes raw bits to the field
470
- #[ inline( always ) ]
557
+ #inline
471
558
pub #unsafety fn #bits( self , value: #fty) -> & ' a mut W {
472
559
self . w. bits = ( self . w. bits & !( #hexmask << #offset) ) | ( ( ( value as #rty) & #hexmask) << #offset) ;
473
560
self . w
@@ -476,33 +563,78 @@ pub fn fields(
476
563
} else {
477
564
quote ! {
478
565
///Writes raw bits to the field
479
- #[ inline( always ) ]
566
+ #inline
480
567
pub #unsafety fn #bits( self , value: #fty) -> & ' a mut W {
481
568
self . w. bits = ( self . w. bits & !#hexmask) | ( ( value as #rty) & #hexmask) ;
482
569
self . w
483
570
}
484
571
}
485
572
} ) ;
486
573
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
+
488
587
mod_items. extend ( quote ! {
489
588
#[ doc = #doc]
490
589
pub struct #_pc_w<' a> {
491
590
w: & ' a mut W ,
591
+ #offset_entry
492
592
}
493
593
494
594
impl <' a> #_pc_w<' a> {
495
595
#proxy_items
496
596
}
497
597
} ) ;
498
598
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
+ } ) ;
504
627
}
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
+ }
506
638
}
507
639
}
508
640
@@ -612,6 +744,41 @@ fn add_from_variants(
612
744
} ) ;
613
745
}
614
746
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
+
615
782
fn derive_from_base (
616
783
mod_items : & mut TokenStream ,
617
784
base : & Base ,
0 commit comments