[CU]reg model构建篇-uvm_reg_map(与前门访问相关)
参考资料:
(1) uvm_reg_map (verificationacademy.com)
(2) uvm_cookbook;
(3) SystemVerilo | UVM | 精讲RAL寄存器模型基础 (qq.com)
1.uvm_reg_map的作用
(1) 每个寄存器在加入寄存器模型时,都有其地址; uvm_reg_map用于存储寄存器的地址,并将其转换成可以访问的物理地址(因为加入寄存器模型中的寄存器地址一般都是偏移地址,而不是绝对地址);
(2) 当寄存器模型使用前门访问方式来实现读或写操作时, uvm_reg_map就会将地址转换成绝对地址,启动一个读或写的sequence,并将读或写的结果返回;
注1:使用uvm_reg_map时,需要指定register access使用的bus agent以及用于实现trans转换的transaction adapter;
注2:在同个数字系统的不同总线视角下,寄存器组可以映射到不同的基地址(base)。因此,一个寄存器组除了可以包含多个寄存器,还可以有多个译码表。(见下文)
2.uvm_reg_map部分源码
1 class uvm_reg_map extends uvm_object; 2 3 `uvm_object_utils(uvm_reg_map) 4 5 // info that is valid only if top-level map 6 // 表示uvm_reg_map所代表的地址空间的基地址; 7 local uvm_reg_addr_t m_base_addr; 8 ... 9 //m_adapter和m_sequencer用于FRONTDOOR操作时,向driver发送item; 10 local uvm_reg_adapter m_adapter; 11 local uvm_sequencer_base m_sequencer; 12 ... 13 local uvm_reg_block m_parent; 14 ... 15 local uvm_reg_map m_parent_map; 16 local uvm_reg_addr_t m_parent_maps[uvm_reg_map]; // value=offset of this map at parent level 17 18 local uvm_reg_addr_t m_submaps[uvm_reg_map]; // value=offset of submap at this level 19 local string m_submap_rights[uvm_reg_map]; // value=rights of submap at this level 20 21 local uvm_reg_map_info m_regs_info[uvm_reg]; 22 local uvm_reg_map_info m_mems_info[uvm_mem]; 23 24 local uvm_reg m_regs_by_offset[uvm_reg_addr_t]; 25 // Use only in addition to above if a RO and a WO 26 // register share the same address. 27 local uvm_reg m_regs_by_offset_wo[uvm_reg_addr_t]; 28 local uvm_mem m_mems_by_offset[uvm_reg_map_addr_range]; 29 ... 30 endclass
3.uvm_reg_map的特点
(1) 一个uvm_reg_block一定要对应一个uvm_reg_map; 系统已经有一个声明好的default_map,只需在uvm_reg_block的build中将其实例化;
(2) uvm_reg_map的实例化,并不是直接调用其new函数,而是通过调用uvm_reg_block的create_map函数来实现;
1 default_map=create_map("default_map",0,2,UVM_BIG_ENDIAN,0);
create_map的参数解释:
参数1的含义:名字;
参数2的含义:基地址;
参数3的含义:系统总线的宽度,该处的单位是byte,而不是bit;
参数4的含义:大小端;
参数5的含义:是否能够按照byte寻址;
4.uvm_reg_map的使用
(1) 寄存器的前门访问操作最终都将由uvm_reg_map完成(需要查看源代码);
(2) 需要在connect_phase中,将转换器和bus_sequencer通过set_sequencer函数告知reg_model的default_map,并将default_map设置为自动预测状态;
1 rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);
5.uvm_reg_map的函数
5.1 add_reg()/add_mem()
(1) 调用该函数可以将register或memory添加到uvm_reg_map中;
5.2 add_submap();
5.3 set_sequencer();
5.4 set_auto_predict();
5.5 do_bus_write()与do_bus_read()(与register前门访问相关);
5.6 set_base_addr();
1 function void uvm_reg_map::set_base_addr(uvm_reg_addr_t offset); 2 if (m_parent_map != null) begin 3 m_parent_map.set_submap_offset(this, offset); 4 end 5 else begin 6 m_base_addr = offset; 7 if (m_parent.is_locked()) begin 8 uvm_reg_map top_map = get_root_map(); 9 top_map.Xinit_address_mapX(); 10 end 11 end 12 endfunction
(1) 修改UVM寄存器映射的基地址;
(2) 可以在lock_model之前或之后调用该函数;如果在lock_model之后调用该函数,地址将会重新初始化;
1 virtual function void build_phase(uvm_phase phase); 2 model.build(); 3 model.APBD.set_base_addr('h2000_0000); 4 model.WSHD.set_base_addr('h3000_0000); 5 model.lock_model(); 6 endfunction
6.uvm_reg_map与uvm_regs关系(多对多的关系)
(1) 在SOC设计中,registers/memory的address mapping通常比较复杂,不是一个单一的map; 当系统中有多个masters时,同一个register可能对应不同的地址,这取决于哪一个bus master访问它;这种情况下,需要将同一个寄存器添加到多个address_map中;
(2) 所谓多对多,指的是多个uvm_reg会添加到同一个uvm_reg_map中; 同一个uvm_reg也可能会添加到多个uvm_reg_map中;
1 //add registers and memories to the AHB_map 2 AHB_map.add_reg(mem_1_offset,32'h00000000,"RW"); 3 AHB_map.add_reg(mem_1_range, 32'h00000004,"RW"); 4 AHB_map.add_reg(mem_2_offset,32'h00000008,"RW"); 5 AHB_map.add_reg(mem_2_range, 32'h0000000c,"RW"); 6 AHB_map.add_reg(mem_3_offset,32'h00000010,"RW"); 7 AHB_map.add_reg(mem_3_range, 32'h00000014,"RW"); 8 AHB_map.add_reg(mem_status, 32'h00000018,"RO"); 9 AHB_map.add_mem(mem_1, 32'hF000_0000,"RW"); 10 AHB_map.add_mem(mem_2, 32'hA000_0000,"RW"); 11 AHB_map.add_mem(mem_3, 32'h0001_0000,"RW"); 12 //add registers and memories to the AHB_2_map; 13 AHB_2_map.add_reg(mem_1_offset, 32'h8000_0000,"RW"); 14 AHB_2_map.add_reg(mem_1_range, 32'h8000_0004,"RW"); 15 AHB_2_map.add_reg(mem_2_offset, 32'h8000_0008,"RW"); 16 AHB_2_map.add_reg(mem_2_range, 32'h8000_000c,"RW");
7.动态address mapping
(1) 在SOC设计中,address map可能因为各种各样的原因而发生变化,如安全性(在某些状态下,register可能不能访问),重新配置,新的host添加到系统中,虚拟化(发生中断时,不同的虚拟机接管公共资源);
(2) register map允许user unlock && reconfigure register block进而支持动态re-mapping;
(3) unlock_model()操作之后,使用unregister()函数可以将register map从register block中移除,新的register map可以添加到register block中;
(4) mapping regsiter可以被unregistered或者added;
7.1动态 address map示例1之对同一address map进行unregister/add reg操作
1 //memeory sub-system (mem_ss) register & memory block; 2 class mem_ss_reg_block extends uvm_reg_block; 3 4 `uvm_object_utils(mem_ss_reg_block) 5 6 function new(string name="mem_ss_reg_block"); 7 super.new(name,build_coverage(UVM_CVR_ADDR_MAP)); 8 endfunction 9 10 //removes mem3 and the registers associated with it from the AHB_map; 11 function void security_demap(); 12 unlock_model(); 13 AHB_map.unregister(mem3_offset); 14 AHB_map.unregister(mem3_range); 15 AHB_map.unregister(mem3); 16 lock_model(); 17 endfunction 18 19 //Re-instates mem3 and the registers associated with it into the AHB_map; 20 function void security_remap(); 21 unlock_model(); //这项功能在uvm1_2中不支持; 22 AHB_map.add_reg(mem_3_offset, 32'h0000_0010,"RW"); 23 AHB_map.add_reg(mem_3_range, 32'h0000_0014,"RW"); 24 AHB_map.add_reg(mem_3, 32'h0001_0000,"RW"); 25 lock_model(); 26 endfunction 27 28 endclass
7.2动态address map示例2之更换整个address map