@@ -32,7 +32,6 @@ pub fn byte_width(bit_width: u32) -> u32 {
3232
3333#[ derive( Clone , Debug ) ]
3434pub struct AddressBlockMemoryInfo {
35- pub name : String ,
3635 pub segment : SegmentBuilder ,
3736 pub segment_flags : SegmentFlags ,
3837 pub section : SectionBuilder ,
@@ -96,9 +95,43 @@ impl DeviceMapper {
9695
9796 // TODO: Add address blocks from derived peripherals?
9897 pub fn map_peripheral_to_view ( & self , view : & BinaryView , peripheral : & PeripheralInfo ) {
98+ // Get the size to extend the current block by.
99+ let extend_block_size = |current_block : & AddressBlock , new_block : & AddressBlock | {
100+ ( new_block. offset + new_block. size - current_block. offset ) . max ( current_block. size )
101+ } ;
102+
103+ let merge_blocks = |mut coalesced_blocks : Vec < AddressBlock > ,
104+ new_block : AddressBlock |
105+ -> Vec < AddressBlock > {
106+ if let Some ( current_block) = coalesced_blocks. last_mut ( ) {
107+ // Check if the new block can be merged with the last block.
108+ // TODO: We don't account for the offset between the blocks
109+ // TODO: Because we dont that means a register block 0x1000 away from another register block
110+ // TODO: will still be merged, which is undesirable considering that SVD address blocks
111+ // TODO: are suppose to be distinct memory regions!
112+ if current_block. usage == new_block. usage {
113+ current_block. size = extend_block_size ( current_block, & new_block) ;
114+ return coalesced_blocks;
115+ }
116+ }
117+ // Push as a new block if not mergeable.
118+ coalesced_blocks. push ( new_block) ;
119+ coalesced_blocks
120+ } ;
121+
99122 if let Some ( address_blocks) = & peripheral. address_block {
100- for address_block in address_blocks {
101- self . map_peripheral_block_to_view ( view, peripheral, address_block) ;
123+ // Because some SVD authors decided to create address blocks for sub-regions
124+ // we must first coalesce all contiguous register address blocks.
125+ let mut sorted_blocks = address_blocks. clone ( ) ;
126+ sorted_blocks. sort_by_key ( |block| block. offset ) ;
127+ let merged_blocks: Vec < AddressBlock > =
128+ sorted_blocks. into_iter ( ) . fold ( Vec :: new ( ) , merge_blocks) ;
129+ // Update the peripheral so downstream usage sees only merged blocks.
130+ let mut updated_peripheral = peripheral. clone ( ) ;
131+ updated_peripheral. address_block = Some ( merged_blocks. clone ( ) ) ;
132+
133+ for address_block in merged_blocks {
134+ self . map_peripheral_block_to_view ( view, & updated_peripheral, & address_block) ;
102135 }
103136 }
104137 }
@@ -115,12 +148,25 @@ impl DeviceMapper {
115148 block_addr,
116149 peripheral. name
117150 ) ;
118- let memory_info = self . peripheral_block_memory_info ( peripheral, address_block) ;
151+
152+ // We don't postfix the block offset in case we only have a single peripheral address block
153+ // as it is unnecessary to talk about a unique block in that case.
154+ let periph_block_len = peripheral. address_block . as_ref ( ) . unwrap ( ) . len ( ) ;
155+ let block_name = if address_block. offset == 0 || periph_block_len == 1 {
156+ // Block name: "PERIPH"
157+ peripheral. name . to_owned ( )
158+ } else {
159+ // Block name: "PERIPH_0x40"
160+ format ! ( "{}_0x{:x}" , peripheral. name, address_block. offset)
161+ } ;
162+
163+ let memory_info =
164+ self . peripheral_block_memory_info ( peripheral, address_block, block_name. clone ( ) ) ;
119165
120166 // Add the block segment, section and backing memory.
121167 let data_memory = DataBuffer :: new ( & vec ! [ 0 ; address_block. size as usize ] ) . unwrap ( ) ;
122168 let added_memory = view. memory_map ( ) . add_data_memory_region (
123- & memory_info . name ,
169+ & block_name ,
124170 block_addr,
125171 & data_memory,
126172 Some ( memory_info. segment_flags ) ,
@@ -131,7 +177,7 @@ impl DeviceMapper {
131177 if !added_memory {
132178 log:: error!(
133179 "Failed to add memory for peripheral block! {} @ 0x{:x}" ,
134- memory_info . name ,
180+ block_name ,
135181 block_addr
136182 ) ;
137183 }
@@ -146,11 +192,11 @@ impl DeviceMapper {
146192 view. set_comment_at ( block_addr, periph_desc) ;
147193 }
148194 // Add register descriptions
149- self . add_comments_for_registers ( view, peripheral, address_block ) ;
195+ self . add_comments_for_registers ( view, peripheral) ;
150196 }
151197
152198 // Registers will get the peripheral type.
153- let peripheral_ty = self . peripheral_type ( peripheral) ;
199+ let peripheral_ty = self . peripheral_type ( peripheral, address_block ) ;
154200 let peripheral_ty_id = format ! ( "SVD:{}" , peripheral. name) ;
155201 let id = view. define_auto_type_with_id (
156202 & peripheral. name ,
@@ -186,19 +232,12 @@ impl DeviceMapper {
186232 }
187233 }
188234
189- pub fn add_comments_for_registers (
190- & self ,
191- view : & BinaryView ,
192- peripheral : & PeripheralInfo ,
193- address_block : & AddressBlock ,
194- ) {
195- let block_addr = peripheral. base_address + address_block. offset as u64 ;
235+ pub fn add_comments_for_registers ( & self , view : & BinaryView , peripheral : & PeripheralInfo ) {
196236 // Adding comments will add a bunch of undo actions.
197237 let undo_id = view. file ( ) . begin_undo_actions ( true ) ;
198238 for register in peripheral. all_registers ( ) {
199- // TODO: The register offset is the enclosing element.
200- // TODO: We need to add a recursive function that keeps track of the offset.
201- let register_addr = block_addr + register. address_offset as u64 ;
239+ // Turns out the "enclosing element" seems to always be the peripheral base address?
240+ let register_addr = peripheral. base_address + register. address_offset as u64 ;
202241 if let Some ( description) = & register. description {
203242 view. set_comment_at ( register_addr, description) ;
204243 }
@@ -253,16 +292,10 @@ impl DeviceMapper {
253292 & self ,
254293 peripheral : & PeripheralInfo ,
255294 address_block : & AddressBlock ,
295+ block_name : String ,
256296 ) -> AddressBlockMemoryInfo {
257297 let block_addr = peripheral. base_address + address_block. offset as u64 ;
258298 let block_range = block_addr..( block_addr + address_block. size as u64 ) ;
259- let block_name = if address_block. offset == 0 {
260- // Block name: "PERIPH"
261- peripheral. name . to_owned ( )
262- } else {
263- // Block name: "PERIPH_0x40"
264- format ! ( "{}_0x{:x}" , peripheral. name, address_block. offset)
265- } ;
266299
267300 let block_access = peripheral. default_register_properties . access ;
268301 let semantics = match block_access {
@@ -292,7 +325,7 @@ impl DeviceMapper {
292325 }
293326 } ;
294327
295- let section = SectionBuilder :: new ( block_name. clone ( ) , block_range. clone ( ) )
328+ let section = SectionBuilder :: new ( block_name, block_range. clone ( ) )
296329 . section_type ( section_type_str)
297330 . semantics ( semantics) ;
298331 let segment_flags = SegmentFlags :: new ( )
@@ -304,7 +337,6 @@ impl DeviceMapper {
304337 let segment = SegmentBuilder :: new ( block_range) . flags ( segment_flags) ;
305338
306339 AddressBlockMemoryInfo {
307- name : block_name,
308340 segment,
309341 segment_flags,
310342 section,
@@ -314,7 +346,11 @@ impl DeviceMapper {
314346 // TODO: In the future we might need to have partial types for each [`AddressBlock`]
315347 // TODO: Support using header name, this requires we define the peripheral type id as the real peripheral name.
316348 // TODO: cont. the reason is so that we can resolve the derived peripheral.
317- pub fn peripheral_type ( & self , peripheral : & PeripheralInfo ) -> Ref < Type > {
349+ pub fn peripheral_type (
350+ & self ,
351+ peripheral : & PeripheralInfo ,
352+ address_block : & AddressBlock ,
353+ ) -> Ref < Type > {
318354 let mut peripheral_struct = StructureBuilder :: new ( ) ;
319355
320356 if let Some ( derived_periph_name) = & peripheral. derived_from {
@@ -327,30 +363,19 @@ impl DeviceMapper {
327363 peripheral_struct. base_structures ( & [ base_struct] ) ;
328364 }
329365
366+ // Take the address block size and use it as the structure width.
330367 // TODO: Support non-contiguous register address blocks (i.e. partial types).
331- if let Some ( address_blocks) = & peripheral. address_block {
332- // If we have more than one address block with registers we likely have an incorrect type.
333- let register_address_blocks: Vec < _ > = address_blocks
334- . iter ( )
335- . filter ( |a| a. usage == AddressBlockUsage :: Registers )
336- . collect ( ) ;
337- if register_address_blocks. len ( ) > 1 {
338- log:: warn!(
339- "Peripheral {} has more than one register address block. The type likely is incorrect." ,
340- peripheral. name
341- ) ;
342- } else if register_address_blocks. len ( ) == 1 {
343- // Take the address block size and use it as the structure width.
344- let register_address_block = register_address_blocks[ 0 ] ;
345- peripheral_struct. width ( register_address_block. size as u64 ) ;
346- }
347- }
368+ peripheral_struct. width ( address_block. size as u64 ) ;
348369
349370 if let Some ( register_clusters) = & peripheral. registers {
350371 for register_cluster in register_clusters {
351372 match register_cluster {
352373 RegisterCluster :: Register ( register) => {
353- let register_member = self . register_member ( register) ;
374+ let mut register_member = self . register_member ( register) ;
375+ // TODO: If we want registers to be relative to the peripheral than we must
376+ // TODO: assert that we create the peripheral type at offset 0 from the base address.
377+ // Make the register member relative to the address block, not the peripheral.
378+ register_member. offset -= address_block. offset as u64 ;
354379 let overwrite = false ; // TODO: Handle overwrites?
355380 peripheral_struct. insert_member ( register_member, overwrite) ;
356381 }
@@ -367,7 +392,6 @@ impl DeviceMapper {
367392 pub fn register_member ( & self , register : & Register ) -> StructureMember {
368393 let register_ty = self . register_type ( register) ;
369394 let conf_register_ty = Conf :: new ( register_ty, MAX_CONFIDENCE ) ;
370- // TODO: Offset in peripheral
371395 StructureMember :: new (
372396 conf_register_ty,
373397 register. name . to_owned ( ) ,
0 commit comments