1
1
use std:: borrow:: Cow ;
2
2
use std:: cmp:: Ordering ;
3
+ use std:: collections:: HashMap ;
3
4
4
- use either:: Either ;
5
5
use quote:: { ToTokens , Tokens } ;
6
- use svd:: { Cluster , ClusterInfo , Defaults , Peripheral , Register } ;
6
+ use svd:: { Cluster , ClusterInfo , Defaults , Peripheral , Register , RegisterCluster , RegisterInfo } ;
7
7
use syn:: { self , Ident } ;
8
8
9
9
use errors:: * ;
@@ -12,25 +12,36 @@ use util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE};
12
12
use generate:: register;
13
13
14
14
pub fn render (
15
- p : & Peripheral ,
15
+ p_original : & Peripheral ,
16
16
all_peripherals : & [ Peripheral ] ,
17
17
defaults : & Defaults ,
18
18
nightly : bool ,
19
19
) -> Result < Vec < Tokens > > {
20
20
let mut out = vec ! [ ] ;
21
21
22
+ let p_derivedfrom = p_original. derived_from . as_ref ( ) . and_then ( |s| {
23
+ all_peripherals. iter ( ) . find ( |x| x. name == * s)
24
+ } ) ;
25
+
26
+ let p_merged = p_derivedfrom. map ( |ancestor| p_original. derive_from ( ancestor) ) ;
27
+ let p = p_merged. as_ref ( ) . unwrap_or ( p_original) ;
28
+
29
+ if p_original. derived_from . is_some ( ) && p_derivedfrom. is_none ( ) {
30
+ eprintln ! ( "Couldn't find derivedFrom original: {} for {}, skipping" ,
31
+ p_original. derived_from. as_ref( ) . unwrap( ) , p_original. name) ;
32
+ return Ok ( out) ;
33
+ }
34
+
22
35
let name_pc = Ident :: new ( & * p. name . to_sanitized_upper_case ( ) ) ;
23
36
let address = util:: hex ( p. base_address ) ;
24
37
let description = util:: escape_brackets ( util:: respace ( p. description . as_ref ( ) . unwrap_or ( & p. name ) ) . as_ref ( ) ) ;
38
+ let derive_regs = p_derivedfrom. is_some ( ) && p_original. registers . is_none ( ) ;
25
39
26
40
let name_sc = Ident :: new ( & * p. name . to_sanitized_snake_case ( ) ) ;
27
- let ( base, derived) = if let Some ( base) = p. derived_from . as_ref ( ) {
28
- // TODO Verify that base exists
29
- // TODO We don't handle inheritance style `derivedFrom`, we should raise
30
- // an error in that case
31
- ( Ident :: new ( & * base. to_sanitized_snake_case ( ) ) , true )
41
+ let base = if derive_regs {
42
+ Ident :: new ( & * p_derivedfrom. unwrap ( ) . name . to_sanitized_snake_case ( ) )
32
43
} else {
33
- ( name_sc. clone ( ) , false )
44
+ name_sc. clone ( )
34
45
} ;
35
46
36
47
// Insert the peripheral structure
@@ -56,17 +67,92 @@ pub fn render(
56
67
}
57
68
} ) ;
58
69
59
- // Derived peripherals do not require re-implementation, and will instead
60
- // use a single definition of the non-derived version
61
- if derived {
70
+ // Derived peripherals may not require re-implementation, and will instead
71
+ // use a single definition of the non-derived version.
72
+ if derive_regs {
62
73
return Ok ( out) ;
63
74
}
64
75
65
76
// erc: *E*ither *R*egister or *C*luster
66
77
let ercs = p. registers . as_ref ( ) . map ( |x| x. as_ref ( ) ) . unwrap_or ( & [ ] [ ..] ) ;
67
-
68
78
let registers: & [ & Register ] = & util:: only_registers ( & ercs) [ ..] ;
79
+
80
+ // make a pass to expand derived registers. Ideally, for the most minimal
81
+ // code size, we'd do some analysis to figure out if we can 100% reuse the
82
+ // code that we're deriving from. For the sake of proving the concept, we're
83
+ // just going to emit a second copy of the accessor code. It'll probably
84
+ // get inlined by the compiler anyway, right? :-)
85
+
86
+ // Build a map so that we can look up registers within this peripheral
87
+ let mut reg_map = HashMap :: new ( ) ;
88
+ for r in registers {
89
+ reg_map. insert ( & r. name , r. clone ( ) ) ;
90
+ }
91
+
92
+ // Compute the effective, derived version of a register given the definition
93
+ // with the derived_from property on it (`info`) and its `ancestor`
94
+ fn derive_reg_info ( info : & RegisterInfo , ancestor : & RegisterInfo ) -> RegisterInfo {
95
+ let mut derived = info. clone ( ) ;
96
+
97
+ if derived. size . is_none ( ) {
98
+ derived. size = ancestor. size . clone ( ) ;
99
+ }
100
+ if derived. access . is_none ( ) {
101
+ derived. access = ancestor. access . clone ( ) ;
102
+ }
103
+ if derived. reset_value . is_none ( ) {
104
+ derived. reset_value = ancestor. reset_value . clone ( ) ;
105
+ }
106
+ if derived. reset_mask . is_none ( ) {
107
+ derived. reset_mask = ancestor. reset_mask . clone ( ) ;
108
+ }
109
+ if derived. fields . is_none ( ) {
110
+ derived. fields = ancestor. fields . clone ( ) ;
111
+ }
112
+ if derived. write_constraint . is_none ( ) {
113
+ derived. write_constraint = ancestor. write_constraint . clone ( ) ;
114
+ }
115
+
116
+ derived
117
+ }
118
+
119
+ // Build up an alternate erc list by expanding any derived registers
120
+ let mut alt_erc : Vec < RegisterCluster > = registers. iter ( ) . filter_map ( |r| {
121
+ match r. derived_from {
122
+ Some ( ref derived) => {
123
+ let ancestor = match reg_map. get ( derived) {
124
+ Some ( r) => r,
125
+ None => {
126
+ eprintln ! ( "register {} derivedFrom missing register {}" , r. name, derived) ;
127
+ return None
128
+ }
129
+ } ;
130
+
131
+ let d = match * * ancestor {
132
+ Register :: Array ( ref info, ref array_info) => {
133
+ Some ( Register :: Array ( derive_reg_info ( * r, info) , array_info. clone ( ) ) . into ( ) )
134
+ }
135
+ Register :: Single ( ref info) => {
136
+ Some ( Register :: Single ( derive_reg_info ( * r, info) ) . into ( ) )
137
+ }
138
+ } ;
139
+
140
+ d
141
+ }
142
+ None => Some ( ( * r) . clone ( ) . into ( ) ) ,
143
+ }
144
+ } ) . collect ( ) ;
145
+
146
+ // Now add the clusters to our alternate erc list
147
+ let clusters = util:: only_clusters ( ercs) ;
148
+ for cluster in & clusters {
149
+ alt_erc. push ( ( * cluster) . clone ( ) . into ( ) ) ;
150
+ }
151
+
152
+ // And revise registers, clusters and ercs to refer to our expanded versions
153
+ let registers: & [ & Register ] = & util:: only_registers ( alt_erc. as_slice ( ) ) [ ..] ;
69
154
let clusters = util:: only_clusters ( ercs) ;
155
+ let ercs = & alt_erc;
70
156
71
157
// No `struct RegisterBlock` can be generated
72
158
if registers. is_empty ( ) && clusters. is_empty ( ) {
@@ -77,7 +163,7 @@ pub fn render(
77
163
78
164
// Push any register or cluster blocks into the output
79
165
let mut mod_items = vec ! [ ] ;
80
- mod_items. push ( register_or_cluster_block ( ercs, defaults, None , nightly) ?) ;
166
+ mod_items. push ( register_or_cluster_block ( ercs. as_slice ( ) , defaults, None , nightly) ?) ;
81
167
82
168
// Push all cluster related information into the peripheral module
83
169
for c in & clusters {
@@ -346,7 +432,7 @@ impl FieldRegions {
346
432
}
347
433
348
434
fn register_or_cluster_block (
349
- ercs : & [ Either < Register , Cluster > ] ,
435
+ ercs : & [ RegisterCluster ] ,
350
436
defs : & Defaults ,
351
437
name : Option < & str > ,
352
438
nightly : bool ,
@@ -359,7 +445,7 @@ fn register_or_cluster_block(
359
445
}
360
446
361
447
fn register_or_cluster_block_stable (
362
- ercs : & [ Either < Register , Cluster > ] ,
448
+ ercs : & [ RegisterCluster ] ,
363
449
defs : & Defaults ,
364
450
name : Option < & str > ,
365
451
) -> Result < Tokens > {
@@ -424,7 +510,7 @@ fn register_or_cluster_block_stable(
424
510
}
425
511
426
512
fn register_or_cluster_block_nightly (
427
- ercs : & [ Either < Register , Cluster > ] ,
513
+ ercs : & [ RegisterCluster ] ,
428
514
defs : & Defaults ,
429
515
name : Option < & str > ,
430
516
) -> Result < Tokens > {
@@ -544,16 +630,16 @@ fn register_or_cluster_block_nightly(
544
630
/// Expand a list of parsed `Register`s or `Cluster`s, and render them to
545
631
/// `RegisterBlockField`s containing `Field`s.
546
632
fn expand (
547
- ercs : & [ Either < Register , Cluster > ] ,
633
+ ercs : & [ RegisterCluster ] ,
548
634
defs : & Defaults ,
549
635
name : Option < & str > ,
550
636
) -> Result < Vec < RegisterBlockField > > {
551
637
let mut ercs_expanded = vec ! [ ] ;
552
638
553
639
for erc in ercs {
554
640
ercs_expanded. extend ( match erc {
555
- Either :: Left ( ref register) => expand_register ( register, defs, name) ?,
556
- Either :: Right ( ref cluster) => expand_cluster ( cluster, defs) ?,
641
+ RegisterCluster :: Register ( ref register) => expand_register ( register, defs, name) ?,
642
+ RegisterCluster :: Cluster ( ref cluster) => expand_cluster ( cluster, defs) ?,
557
643
} ) ;
558
644
}
559
645
@@ -569,15 +655,15 @@ fn cluster_size_in_bits(info: &ClusterInfo, defs: &Defaults) -> Result<u32> {
569
655
570
656
for c in & info. children {
571
657
let end = match * c {
572
- Either :: Left ( ref reg) => {
658
+ RegisterCluster :: Register ( ref reg) => {
573
659
let reg_size: u32 = expand_register ( reg, defs, None ) ?
574
660
. iter ( )
575
661
. map ( |rbf| rbf. size )
576
662
. sum ( ) ;
577
663
578
664
( reg. address_offset * BITS_PER_BYTE ) + reg_size
579
665
}
580
- Either :: Right ( ref clust) => {
666
+ RegisterCluster :: Cluster ( ref clust) => {
581
667
( clust. address_offset * BITS_PER_BYTE ) + cluster_size_in_bits ( clust, defs) ?
582
668
}
583
669
} ;
0 commit comments