@@ -4,6 +4,13 @@ use anyhow::{Context, Result};
4
4
use std:: { fs:: File , io:: Read , path:: Path } ;
5
5
use svd:: PeripheralInfo ;
6
6
use svd_parser:: svd:: { self , Cluster , Field , Peripheral , Register , RegisterCluster , RegisterInfo } ;
7
+ use svd_rs:: FieldInfo ;
8
+
9
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Default ) ]
10
+ struct CoveredFields {
11
+ all : u32 ,
12
+ covered : u32 ,
13
+ }
7
14
8
15
/// Output sorted text of every peripheral, register, field, and interrupt
9
16
/// in the device, such that automated diffing is possible.
@@ -28,28 +35,46 @@ fn get_text<R: Read>(svd: &mut R) -> Result<String> {
28
35
29
36
fn to_text ( peripherals : & [ Peripheral ] ) -> String {
30
37
let mut mmap: Vec < String > = vec ! [ ] ;
38
+ let mut coverage = CoveredFields :: default ( ) ;
31
39
32
40
for p in peripherals {
33
41
match p {
34
42
Peripheral :: Single ( p) => {
35
43
get_peripheral ( p, & mut mmap) ;
36
44
get_interrupts ( p, & mut mmap) ;
37
45
let registers = get_periph_registers ( p, peripherals) ;
38
- get_registers ( p. base_address , registers. as_ref ( ) , "" , & mut mmap) ;
46
+ get_registers (
47
+ p. base_address ,
48
+ registers. as_ref ( ) ,
49
+ "" ,
50
+ & mut mmap,
51
+ & mut coverage,
52
+ ) ;
39
53
}
40
54
Peripheral :: Array ( p, d) => {
41
55
for pi in svd:: peripheral:: expand ( p, d) {
42
56
get_peripheral ( & pi, & mut mmap) ;
43
57
get_interrupts ( & pi, & mut mmap) ;
44
58
let registers = get_periph_registers ( & pi, peripherals) ;
45
- get_registers ( pi. base_address , registers. as_ref ( ) , "" , & mut mmap) ;
59
+ get_registers (
60
+ pi. base_address ,
61
+ registers. as_ref ( ) ,
62
+ "" ,
63
+ & mut mmap,
64
+ & mut coverage,
65
+ ) ;
46
66
}
47
67
}
48
68
}
49
69
}
50
70
51
71
mmap. sort ( ) ;
52
- mmap. join ( "\n " )
72
+ let mut mmap = mmap. join ( "\n " ) ;
73
+ mmap. push_str ( & format ! (
74
+ "\n Covered {} from {} fields." ,
75
+ coverage. covered, coverage. all
76
+ ) ) ;
77
+ mmap
53
78
}
54
79
55
80
fn get_periph_registers < ' a > (
@@ -104,6 +129,7 @@ fn get_registers(
104
129
registers : Option < & Vec < RegisterCluster > > ,
105
130
suffix : & str ,
106
131
mmap : & mut Vec < String > ,
132
+ coverage : & mut CoveredFields ,
107
133
) {
108
134
if let Some ( registers) = registers {
109
135
for r in registers {
@@ -121,7 +147,7 @@ fn get_registers(
121
147
"{addr} B REGISTER {rname}{derived}{access}: {description}"
122
148
) ;
123
149
mmap. push ( text) ;
124
- get_fields ( r, & addr, mmap) ;
150
+ get_fields ( r, & addr, mmap, coverage ) ;
125
151
}
126
152
Register :: Array ( r, d) => {
127
153
for ri in svd:: register:: expand ( r, d) {
@@ -134,7 +160,7 @@ fn get_registers(
134
160
"{addr} B REGISTER {rname}{derived}{access}: {description}"
135
161
) ;
136
162
mmap. push ( text) ;
137
- get_fields ( & ri, & addr, mmap) ;
163
+ get_fields ( & ri, & addr, mmap, coverage ) ;
138
164
}
139
165
}
140
166
}
@@ -149,7 +175,7 @@ fn get_registers(
149
175
let description = str_utils:: get_description ( & c. description ) ;
150
176
let text = format ! ( "{addr} B CLUSTER {cname}{derived}: {description}" ) ;
151
177
mmap. push ( text) ;
152
- get_registers ( caddr, Some ( & c. children ) , "" , mmap) ;
178
+ get_registers ( caddr, Some ( & c. children ) , "" , mmap, coverage ) ;
153
179
}
154
180
Cluster :: Array ( c, d) => {
155
181
for ( ci, idx) in svd:: cluster:: expand ( c, d) . zip ( d. indexes ( ) ) {
@@ -160,7 +186,7 @@ fn get_registers(
160
186
let text =
161
187
format ! ( "{addr} B CLUSTER {cname}{derived}: {description}" ) ;
162
188
mmap. push ( text) ;
163
- get_registers ( caddr, Some ( & c. children ) , & idx, mmap) ;
189
+ get_registers ( caddr, Some ( & c. children ) , & idx, mmap, coverage ) ;
164
190
}
165
191
}
166
192
}
@@ -170,7 +196,12 @@ fn get_registers(
170
196
}
171
197
}
172
198
173
- fn get_fields ( register : & RegisterInfo , addr : & str , mmap : & mut Vec < String > ) {
199
+ fn get_fields (
200
+ register : & RegisterInfo ,
201
+ addr : & str ,
202
+ mmap : & mut Vec < String > ,
203
+ coverage : & mut CoveredFields ,
204
+ ) {
174
205
if let Some ( fields) = & register. fields {
175
206
for f in fields {
176
207
let derived = derived_str ( & f. derived_from ) ;
@@ -185,6 +216,12 @@ fn get_fields(register: &RegisterInfo, addr: &str, mmap: &mut Vec<String>) {
185
216
"{addr} C FIELD {bit_offset:02}w{bit_width:02} {fname}{derived}{access}: {description}"
186
217
) ;
187
218
mmap. push ( text) ;
219
+ if f. derived_from . is_none ( ) {
220
+ coverage. all += 1 ;
221
+ if is_covered ( f) {
222
+ coverage. covered += 1 ;
223
+ }
224
+ }
188
225
}
189
226
Field :: Array ( f, d) => {
190
227
for fi in svd:: field:: expand ( f, d) {
@@ -195,14 +232,24 @@ fn get_fields(register: &RegisterInfo, addr: &str, mmap: &mut Vec<String>) {
195
232
let text = format ! (
196
233
"{addr} C FIELD {bit_offset:02}w{bit_width:02} {fname}{derived}{access}: {description}"
197
234
) ;
198
- mmap. push ( text) ;
235
+ if fi. derived_from . is_none ( ) {
236
+ mmap. push ( text) ;
237
+ coverage. all += 1 ;
238
+ if is_covered ( & fi) {
239
+ coverage. covered += 1 ;
240
+ }
241
+ }
199
242
}
200
243
}
201
244
}
202
245
}
203
246
}
204
247
}
205
248
249
+ fn is_covered ( f : & FieldInfo ) -> bool {
250
+ !f. enumerated_values . is_empty ( ) || f. write_constraint . is_some ( )
251
+ }
252
+
206
253
#[ cfg( test) ]
207
254
mod tests {
208
255
use super :: * ;
@@ -231,6 +278,12 @@ mod tests {
231
278
<description>Field 1</description>
232
279
<bitOffset>5</bitOffset>
233
280
<bitWidth>2</bitWidth>
281
+ <writeConstraint>
282
+ <range>
283
+ <minimum>0</minimum>
284
+ <maximum>0x3</maximum>
285
+ </range>
286
+ </writeConstraint>
234
287
</field>
235
288
<field>
236
289
<name>F2</name>
@@ -261,6 +314,27 @@ mod tests {
261
314
<name>REG1</name>
262
315
<addressOffset>0x10</addressOffset>
263
316
<description>Register B1</description>
317
+ <fields>
318
+ <field>
319
+ <name>F3</name>
320
+ <description>Field 3</description>
321
+ <bitOffset>10</bitOffset>
322
+ <bitWidth>1</bitWidth>
323
+ <enumeratedValues>
324
+ <name>EV_NAME</name>
325
+ <enumeratedValue>
326
+ <name>VAL1</name>
327
+ <description>Value description 1</description>
328
+ <value>0</value>
329
+ </enumeratedValue>
330
+ <enumeratedValue>
331
+ <name>VAL2</name>
332
+ <description>Value description 2</description>
333
+ <value>1</value>
334
+ </enumeratedValue>
335
+ </enumeratedValues>
336
+ </field>
337
+ </fields>
264
338
</register>
265
339
</registers>
266
340
</peripheral>
@@ -274,8 +348,10 @@ mod tests {
274
348
0x10000014 B REGISTER REG2: Register A2
275
349
0x10010000 A PERIPHERAL PeriphB
276
350
0x10010010 B REGISTER REG1: Register B1
351
+ 0x10010010 C FIELD 10w01 F3: Field 3
277
352
INTERRUPT 001: INT_A1 (PeriphA): Interrupt A1
278
- INTERRUPT 002: INT_B2 (PeriphB): Interrupt B2" ;
353
+ INTERRUPT 002: INT_B2 (PeriphB): Interrupt B2
354
+ Covered 2 from 3 fields." ;
279
355
280
356
#[ test]
281
357
fn mmap ( ) {
0 commit comments