@@ -46,6 +46,10 @@ pub trait PeripheralExt {
4646 /// Add rname given by radd to ptag
4747 fn add_register ( & mut self , rname : & str , radd : & Hash ) -> PatchResult ;
4848
49+ /// Remove fields from rname and mark it as derivedFrom rderive.
50+ /// Update all derivedFrom referencing rname
51+ fn derive_register ( & mut self , rname : & str , rderive : & Yaml ) -> PatchResult ;
52+
4953 /// Add rname given by deriving from rsource to ptag
5054 fn copy_register ( & mut self , rname : & str , rderive : & Hash ) -> PatchResult ;
5155
@@ -158,6 +162,14 @@ impl PeripheralExt for Peripheral {
158162 }
159163 }
160164
165+ // Handle any copied peripherals
166+ for ( rname, rderive) in pmod. hash_iter ( "_copy" ) {
167+ let rderive = rderive. hash ( ) ?;
168+ let rname = rname. str ( ) ?;
169+ self . copy_register ( rname, rderive)
170+ . with_context ( || format ! ( "Copying register `{}`" , rname) ) ?
171+ }
172+
161173 // Handle modifications
162174 for ( rspec, rmod) in pmod. hash_iter ( "_modify" ) {
163175 let rmod = rmod. hash ( ) ?;
@@ -237,25 +249,27 @@ impl PeripheralExt for Peripheral {
237249 }
238250
239251 for ( rname, rderive) in pmod. hash_iter ( "_derive" ) {
240- let rderive = rderive. hash ( ) ?;
241252 let rname = rname. str ( ) ?;
242253 match rname {
243254 "_registers" => {
244- for ( rname, val) in rderive {
255+ for ( rname, val) in rderive. hash ( ) ? {
245256 let rname = rname. str ( ) ?;
246- self . copy_register ( rname, val. hash ( ) ?)
247- . with_context ( || format ! ( "Copying register `{}`" , rname) ) ?;
257+ self . derive_register ( rname, val) . with_context ( || {
258+ format ! ( "Deriving register `{}` from `{:?}`" , rname, val)
259+ } ) ?;
248260 }
249261 }
250- "_interrupts " => {
262+ "_clusters " => {
251263 return Err ( anyhow ! (
252- "deriving interrupts not implemented yet: {}" ,
264+ "deriving clusters is not implemented yet: {}" ,
253265 rname
254266 ) )
255267 }
256- _ => self
257- . copy_register ( rname, rderive)
258- . with_context ( || format ! ( "Copying register `{}`" , rname) ) ?,
268+ _ => {
269+ self . derive_register ( rname, rderive) . with_context ( || {
270+ format ! ( "Deriving register `{}` from `{:?}`" , rname, rderive)
271+ } ) ?;
272+ }
259273 }
260274 }
261275
@@ -343,6 +357,47 @@ impl PeripheralExt for Peripheral {
343357 Ok ( ( ) )
344358 }
345359
360+ fn derive_register ( & mut self , rname : & str , rderive : & Yaml ) -> PatchResult {
361+ let ( rderive, info) = if let Some ( rderive) = rderive. as_str ( ) {
362+ (
363+ rderive,
364+ RegisterInfo :: builder ( ) . derived_from ( Some ( rderive. into ( ) ) ) ,
365+ )
366+ } else if let Some ( hash) = rderive. as_hash ( ) {
367+ let rderive = hash. get_str ( "_from" ) ?. ok_or_else ( || {
368+ anyhow ! (
369+ "derive: source register not given, please add a _from field to {}" ,
370+ rname
371+ )
372+ } ) ?;
373+ (
374+ rderive,
375+ make_register ( hash) ?. derived_from ( Some ( rderive. into ( ) ) ) ,
376+ )
377+ } else {
378+ return Err ( anyhow ! ( "derive: incorrect syntax for {}" , rname) ) ;
379+ } ;
380+ self . get_register ( rderive)
381+ . ok_or_else ( || anyhow ! ( "register {} not found" , rderive) ) ?;
382+
383+ match self . get_mut_register ( rname) {
384+ Some ( register) => register. modify_from ( info, VAL_LVL ) ?,
385+ None => {
386+ let register = info. name ( rname. into ( ) ) . build ( VAL_LVL ) ?. single ( ) ;
387+ self . registers
388+ . get_or_insert_with ( Default :: default)
389+ . push ( RegisterCluster :: Register ( register) ) ;
390+ }
391+ }
392+ for r in self
393+ . registers_mut ( )
394+ . filter ( |r| r. derived_from . as_deref ( ) == Some ( rname) )
395+ {
396+ r. derived_from = Some ( rderive. into ( ) ) ;
397+ }
398+ Ok ( ( ) )
399+ }
400+
346401 fn copy_register ( & mut self , rname : & str , rderive : & Hash ) -> PatchResult {
347402 let srcname = rderive. get_str ( "_from" ) ?. ok_or_else ( || {
348403 anyhow ! (
0 commit comments