Acquire a Register Model
寄存器模型一般可以使用工具生成或者從頭開始編寫,寄存器模型示例如下:
Filename regmodel.sv class dummy_reg extends uvm_reg; `uvm_object_utils(dummy_reg) rand uvm_reg_field F; ... virtual function void build(); F = uvm_reg_field::create("F"); F.configure(this, 8, 0, "RW", 1, 8'h00, 1, 1, 1); endfunction endclass class bus_reg_block extends uvm_reg_block; `uvm_object_utils(bus_reg_block) rand dummy_reg reg0; uvm_reg_map bus_map; ... virtual function void build(); reg0 = dummy_reg::create("reg0"); reg0.configure(this); reg0.build(); bus_map = create_map("bus_map", 'h0, 1, UVM_LITTLE_ENDIAN); default_map = bus_map; bus_map.add_reg(reg0, 'h0, "RW"); lock_model(); endfunction endclass class top_reg_block extends uvm_reg_block; `uvm_object_utils(top_reg_block) bus_reg_block bus; uvm_reg_map bus_map; ... virtual function void build(); bus = bus_reg_block::create("bus"); bus.configure(this); bus.build(); bus_map = create_map("bus_map", 'h0, 1, UVM_LITTLE_ENDIAN); default_map = bus_map; bus_map.add_submap(bus.bus_map, 'h0); lock_model(); endfunction endclass
Add Register Access to the Interface Template File
我們從interface template file的主要部分開始,其中指定了事務和接口中的變量。為了使示例簡單,我們省略monitor和focv,只包含driver。
Filename bus.tpl agent_name = bus trans_item = bus_tx trans_var = rand bit cmd; trans_var = rand byte addr; trans_var = rand byte data; driver_inc = bus_do_drive.sv if_port = logic clk; if_port = bit cmd; if_port = byte addr; if_port = byte data; if_clock = clk
現(xiàn)在,我們通過指定register layer具有的訪問類型以及寄存器層和agent之間的映射來擴展interface template file。這是通過標識register layer用于讀取和寫入 DUT 中的寄存器的command, address和data:
reg_access_mode = WR reg_access_block_type = bus_reg_block uvm_reg_kind = cmd uvm_reg_addr = addr uvm_reg_data = data
reg_access_mode指定是否允許register layer對寄存器進行寫/讀(WR)、只寫 (WO) 或只讀 (RO) 訪問。
reg_access_block_type在寄存器模型文件中指定 uvm_reg_block 類型,該文件包含要讀取或?qū)懭氲募拇嫫鳌?/p>
Add Register Access to the Common Template File
top-level register model必須在common template file中向uvm代碼生成器描述:
Filename common.tpl regmodel_file = regmodel.sv top_reg_block_type = top_reg_block
top_reg_block_type參數(shù)必須為top-level register model的類名。
Generate and Run
uvm代碼生成器將創(chuàng)建以下結(jié)構(gòu):
top_tb (module) ? top_th (module instance) ? bus_if (interface instance) mydut (module instance) ? top_test (object, class uvm_test) ? top_config (created in build_phase, class uvm_object) top_env (uvm_env) ? bus_env_config (uvm_object) top_reg_block (uvm_reg_block) bus_env (uvm_env) ? bus_config (uvm_object) bus_reg_block (uvm_reg_block) reg2bus_adapter uvm_reg_predictor bus_agent (uvm_agent) ? bus_sequencer bus_driver (uvm_driver) bus_monitor (uvm_monitor) bus_coverage (uvm_subscriber) bus_env_coverage (uvm_subscriber) ? top_default_seq (created in run_phase, class uvm_sequence) ? bus_env_default_seq (uvm_sequence) ? registers.update()
實例化register model時,使用register model的每個agent都在其自己的 env 中實例化。在上面的結(jié)構(gòu)中,可以看到:
top_test instantiates top_env instantiates bus_env instantiates bus_agent
top_env具有對top-level register blocktop_reg_block的引用,registermodel就是在這個層次實例化的。
bus_env引用該agent的register modelbus_reg_block,并實例化adapter和predictor,該adapter和predictor將該registermodel連接到agent。
uvm代碼生成器在使用registermodel的default sequence中向相應registermodel中的每個寄存器寫入一個隨機值。
Filenamebus_env_seq_lib.sv task bus_env_default_seq::body(); super.body(); `uvm_info(get_type_name(), "default sequence starting", UVM_HIGH) regmodel.get_registers(data_regs); data_regs.shuffle(); foreach(data_regs[i]) begin // Randomize register content and then update if(!data_regs[i].randomize()) `uvm_error(get_type_name(), $sformatf("Randomization error for data_regs[%0d]", i)) data_regs[i].update(status, .path(UVM_FRONTDOOR), .parent(this)); end `uvm_info(get_type_name(), "default sequence completed", UVM_HIGH) endtask : body
添加用戶定義的寄存器sequence
與前面的文章一樣,可以通過擴展uvm代碼生成器創(chuàng)建的default sequence來創(chuàng)建自己的sequence。這次它是一個專門的register sequence:
Filenamebus_env_reg_seq.sv class bus_env_reg_seq extends bus_env_default_seq; `uvm_object_utils(bus_env_reg_seq) ... task body(); regmodel.reg0.write(status, .value('hab), .parent(this)); assert(status == UVM_IS_OK); regmodel.reg0.write(status, .value('hcd), .parent(this)); assert(status == UVM_IS_OK); regmodel.reg0.write(status, .value('hef), .parent(this)); assert(status == UVM_IS_OK); regmodel.reg0.read(status, .value(data), .parent(this)); assert(status == UVM_IS_OK); endtask: body endclass : bus_env_reg_seq
同樣需要在interface template file添加factory override:
Filenamebus.tpl ... reg_seq_inc = bus_env_reg_seq.sv agent_factory_set = bus_env_default_seq bus_env_reg_seq
然后可以對生成的現(xiàn)成代碼運行仿真,應該看到仿真日志中包含以下打印信息:
# @10000 mydut bus_cmd = W, bus_addr = 00, bus_data = ab # @30000 mydut bus_cmd = W, bus_addr = 00, bus_data = cd # @50000 mydut bus_cmd = W, bus_addr = 00, bus_data = ef # @70000 mydut bus_cmd = R, bus_addr = 00, bus_data = 00
審核編輯:劉清
-
寄存器
+關(guān)注
關(guān)注
31文章
5302瀏覽量
119875 -
UVM
+關(guān)注
關(guān)注
0文章
181瀏覽量
19122 -
生成器
+關(guān)注
關(guān)注
7文章
313瀏覽量
20958 -
DUT
+關(guān)注
關(guān)注
0文章
189瀏覽量
12314
原文標題:Easier UVM Code Generator Part 3:添加Register Layer
文章出處:【微信號:芯片驗證工程師,微信公眾號:芯片驗證工程師】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論