@@ -4,6 +4,13 @@ use anyhow::{Context, Result};
44use std:: { fs:: File , io:: Read , path:: Path } ;
55use svd:: PeripheralInfo ;
66use 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+ }
714
815/// Output sorted text of every peripheral, register, field, and interrupt
916/// in the device, such that automated diffing is possible.
@@ -28,28 +35,46 @@ fn get_text<R: Read>(svd: &mut R) -> Result<String> {
2835
2936fn to_text ( peripherals : & [ Peripheral ] ) -> String {
3037 let mut mmap: Vec < String > = vec ! [ ] ;
38+ let mut coverage = CoveredFields :: default ( ) ;
3139
3240 for p in peripherals {
3341 match p {
3442 Peripheral :: Single ( p) => {
3543 get_peripheral ( p, & mut mmap) ;
3644 get_interrupts ( p, & mut mmap) ;
3745 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+ ) ;
3953 }
4054 Peripheral :: Array ( p, d) => {
4155 for pi in svd:: peripheral:: expand ( p, d) {
4256 get_peripheral ( & pi, & mut mmap) ;
4357 get_interrupts ( & pi, & mut mmap) ;
4458 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+ ) ;
4666 }
4767 }
4868 }
4969 }
5070
5171 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
5378}
5479
5580fn get_periph_registers < ' a > (
@@ -104,6 +129,7 @@ fn get_registers(
104129 registers : Option < & Vec < RegisterCluster > > ,
105130 suffix : & str ,
106131 mmap : & mut Vec < String > ,
132+ coverage : & mut CoveredFields ,
107133) {
108134 if let Some ( registers) = registers {
109135 for r in registers {
@@ -121,7 +147,7 @@ fn get_registers(
121147 "{addr} B REGISTER {rname}{derived}{access}: {description}"
122148 ) ;
123149 mmap. push ( text) ;
124- get_fields ( r, & addr, mmap) ;
150+ get_fields ( r, & addr, mmap, coverage ) ;
125151 }
126152 Register :: Array ( r, d) => {
127153 for ri in svd:: register:: expand ( r, d) {
@@ -134,7 +160,7 @@ fn get_registers(
134160 "{addr} B REGISTER {rname}{derived}{access}: {description}"
135161 ) ;
136162 mmap. push ( text) ;
137- get_fields ( & ri, & addr, mmap) ;
163+ get_fields ( & ri, & addr, mmap, coverage ) ;
138164 }
139165 }
140166 }
@@ -149,7 +175,7 @@ fn get_registers(
149175 let description = str_utils:: get_description ( & c. description ) ;
150176 let text = format ! ( "{addr} B CLUSTER {cname}{derived}: {description}" ) ;
151177 mmap. push ( text) ;
152- get_registers ( caddr, Some ( & c. children ) , "" , mmap) ;
178+ get_registers ( caddr, Some ( & c. children ) , "" , mmap, coverage ) ;
153179 }
154180 Cluster :: Array ( c, d) => {
155181 for ( ci, idx) in svd:: cluster:: expand ( c, d) . zip ( d. indexes ( ) ) {
@@ -160,7 +186,7 @@ fn get_registers(
160186 let text =
161187 format ! ( "{addr} B CLUSTER {cname}{derived}: {description}" ) ;
162188 mmap. push ( text) ;
163- get_registers ( caddr, Some ( & c. children ) , & idx, mmap) ;
189+ get_registers ( caddr, Some ( & c. children ) , & idx, mmap, coverage ) ;
164190 }
165191 }
166192 }
@@ -170,7 +196,12 @@ fn get_registers(
170196 }
171197}
172198
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+ ) {
174205 if let Some ( fields) = & register. fields {
175206 for f in fields {
176207 let derived = derived_str ( & f. derived_from ) ;
@@ -185,6 +216,12 @@ fn get_fields(register: &RegisterInfo, addr: &str, mmap: &mut Vec<String>) {
185216 "{addr} C FIELD {bit_offset:02}w{bit_width:02} {fname}{derived}{access}: {description}"
186217 ) ;
187218 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+ }
188225 }
189226 Field :: Array ( f, d) => {
190227 for fi in svd:: field:: expand ( f, d) {
@@ -195,14 +232,24 @@ fn get_fields(register: &RegisterInfo, addr: &str, mmap: &mut Vec<String>) {
195232 let text = format ! (
196233 "{addr} C FIELD {bit_offset:02}w{bit_width:02} {fname}{derived}{access}: {description}"
197234 ) ;
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+ }
199242 }
200243 }
201244 }
202245 }
203246 }
204247}
205248
249+ fn is_covered ( f : & FieldInfo ) -> bool {
250+ !f. enumerated_values . is_empty ( ) || f. write_constraint . is_some ( )
251+ }
252+
206253#[ cfg( test) ]
207254mod tests {
208255 use super :: * ;
@@ -231,6 +278,12 @@ mod tests {
231278 <description>Field 1</description>
232279 <bitOffset>5</bitOffset>
233280 <bitWidth>2</bitWidth>
281+ <writeConstraint>
282+ <range>
283+ <minimum>0</minimum>
284+ <maximum>0x3</maximum>
285+ </range>
286+ </writeConstraint>
234287 </field>
235288 <field>
236289 <name>F2</name>
@@ -261,6 +314,27 @@ mod tests {
261314 <name>REG1</name>
262315 <addressOffset>0x10</addressOffset>
263316 <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>
264338 </register>
265339 </registers>
266340 </peripheral>
@@ -274,8 +348,10 @@ mod tests {
2743480x10000014 B REGISTER REG2: Register A2
2753490x10010000 A PERIPHERAL PeriphB
2763500x10010010 B REGISTER REG1: Register B1
351+ 0x10010010 C FIELD 10w01 F3: Field 3
277352INTERRUPT 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." ;
279355
280356 #[ test]
281357 fn mmap ( ) {
0 commit comments