I have a question of how to reuse a block reg_block to a multi-processor SOC system level.
Usually a block has only one configuration interface(AHB, for example), so in the block level environment, it will instantiate its UVM register block(block register model) which only has one UVM register map.
But when the block is reused to the system, especially for a multi-processor system, there should be multiple register maps, and different register map is for different processor. How can we reuse the block register model to the system level and incorporate multiple register maps?
A graceful(also natural) way in my mind is that we should create a top reg_block for the system level with multiple register maps which has a reference to the block register model, and call add_submap() API to add the UVM register map defined in the block register model into different register maps in system level, but it seems to me that the current UVM can’t support adding one UVM register map into multiple parent register maps. (i.e. UVM reg_map can’t support multiple parents, see below code snippets for details)
Can anyone give some suggestions on how to handle that? Thanks a lot!
P.S the relevant UVM source code snippets are as below:
function void uvm_reg_map::add_submap (uvm_reg_map child_map,
957 uvm_reg_addr_t offset);
958 uvm_reg_map parent_map;
959
960 if (child_map == null) begin
961 uvm_error("RegModel", {"Attempting to add NULL map to map '",get_full_name(),"'"}) 962 return; 963 end 964 965 parent_map = child_map.get_parent_map(); 966 **967 // Can not have more than one parent (currently) 968 if (parent_map != null) begin 969
uvm_error(“RegModel”, {“Map '”, child_map.get_full_name(),
970 “’ is already a child of map '”,
971 parent_map.get_full_name(),
972 “'. Cannot also be a child of map '”,
973 get_full_name(),
974 “'”})__
975 return;
976 end**
977
978 begin : parent_block_check
979 uvm_reg_block child_blk = child_map.get_parent();
980 if (child_blk == null) begin
981 uvm_error("RegModel", {"Cannot add submap '",child_map.get_full_name(), 982 "' because it does not have a parent block"}) 983 return; 984 end 985 if (get_parent() != child_blk.get_parent()) begin 986
uvm_error(“RegModel”,
987 {“Submap '”,child_map.get_full_name(),“’ may not be added to this “,
988 “address map, '”, get_full_name(),”', as the submap’s parent block, '”,
989 child_blk.get_full_name(),“', is not a child of this map’s parent block, '”,
990 m_parent.get_full_name(),“'”})
991 return;
992 end
993 end
994
995 begin : n_bytes_match_check
996 if (m_n_bytes > child_map.get_n_bytes(UVM_NO_HIER)) begin
997 `uvm_warning(“RegModel”,
998 $sformatf(“Adding %0d-byte submap ‘%s’ to %0d-byte parent map ‘%s’”,
999 child_map.get_n_bytes(UVM_NO_HIER), child_map.get_full_name(),
1000 m_n_bytes, get_full_name()));
1001 end
1002 end
1003
1004 child_map.add_parent_map(this,offset);
1005
1006 set_submap_offset(child_map, offset);
1007
1008 endfunction: add_submap