

编写excel文件,后缀为csv;编写python脚本
才cmd中输入这两个文件的路径和命名就可以自动生成寄存器模型rgm


最开始的寄存器模型是这样的

在reg_pkg中,这些接口信号作为uvm_sequence_item定义为reg_trans类。约束,注册,域的自动化,new函数,一个不要落。
- class reg_trans extends uvm_sequence_item;
- rand bit[7:0] addr;
- rand bit[1:0] cmd;
- rand bit[31:0] data;
- bit rsp;
-
- constraint cstr {
- soft cmd inside {`WRITE, `READ, `IDLE};
- soft addr inside {`SLV0_RW_ADDR, `SLV1_RW_ADDR, `SLV2_RW_ADDR, `SLV0_R_ADDR, `SLV1_R_ADDR, `SLV2_R_ADDR};
- addr[7:4]==0 && cmd==`WRITE -> soft data[31:6]==0;
- soft addr[7:5]==0;
- addr[4]==1 -> soft cmd == `READ;
- };
-
- `uvm_object_utils_begin(reg_trans)
- `uvm_field_int(addr, UVM_ALL_ON)
- `uvm_field_int(cmd, UVM_ALL_ON)
- `uvm_field_int(data, UVM_ALL_ON)
- `uvm_field_int(rsp, UVM_ALL_ON)
- `uvm_object_utils_end
-
- function new (string name = "reg_trans");
- super.new(name);
- endfunction
- endclass

item由driver驱动
- class reg_driver extends uvm_driver #(reg_trans);
- local virtual reg_intf intf;
-
- `uvm_component_utils(reg_driver)
-
- function new (string name = "reg_driver", uvm_component parent);
- super.new(name, parent);
- endfunction
-
- function void set_interface(virtual reg_intf intf);
- if(intf == null)
- $error("interface handle is NULL, please check if target interface has been intantiated");
- else
- this.intf = intf;
- endfunction
-
- task run_phase(uvm_phase phase);
- fork
- this.do_drive();
- this.do_reset();
- join
- endtask
-
- task do_reset();
- forever begin
- @(negedge intf.rstn);
- intf.cmd_addr <= 0;
- intf.cmd <= `IDLE;
- intf.cmd_data_m2s <= 0;
- end
- endtask
-
- task do_drive();
- reg_trans req, rsp;
- @(posedge intf.rstn);
- forever begin
- seq_item_port.get_next_item(req);
- this.reg_write(req);
- void'($cast(rsp, req.clone()));
- rsp.rsp = 1;
- rsp.set_sequence_id(req.get_sequence_id());
- seq_item_port.item_done(rsp);
- end
- endtask
-
- task reg_write(reg_trans t);
- @(posedge intf.clk iff intf.rstn);
- case(t.cmd)
- `WRITE: begin
- intf.drv_ck.cmd_addr <= t.addr;
- intf.drv_ck.cmd <= t.cmd;
- intf.drv_ck.cmd_data_m2s <= t.data;
- end
- `READ: begin
- intf.drv_ck.cmd_addr <= t.addr;
- intf.drv_ck.cmd <= t.cmd;
- repeat(2) @(negedge intf.clk);
- t.data = intf.cmd_data_s2m;
- end
- `IDLE: begin
- this.reg_idle();
- end
- default: $error("command %b is illegal", t.cmd);
- endcase
- `uvm_info(get_type_name(), $sformatf("sent addr %2x, cmd %2b, data %8x", t.addr, t.cmd, t.data), UVM_HIGH)
- endtask
-
- task reg_idle();
- @(posedge intf.clk);
- intf.drv_ck.cmd_addr <= 0;
- intf.drv_ck.cmd <= `IDLE;
- intf.drv_ck.cmd_data_m2s <= 0;
- endtask
- endclass


一共6个寄存器对应的csv文档如下

更新后的结构图如下,寄存器被换成了APB总线?

寄存器接口如下


根据v1.csv和寄存器图,以及寄存器接口中的信号,更新寄存器为v2

这是自己的傻逼更新,需要更改的地方是:预留区域reserved为RO只读,id的重置值不是全部为0;域不是信号名;free slot的重置值时'd32

用相同的操作获得rgm.pkg。寄存器模型每个reg为一个类,最后多一个类mcdf_reg

每个寄存器类的结构都是相似的:注册,声明域,域的覆盖组;new函数中有条件例化覆盖组;build_phase完成域的例化和配置;与覆盖组相对应的采样函数。
在最后的mcdf_rgm中,所有寄存器class被作为随机变量,声明寄存器map,build_phase中对每个寄存器进行例化、配置、调用build、例化map+每个寄存器偏移地址,预留了后门访问的添加路径。最后是lock_model,这部分要再复习一下uvm的寄存器模型。
- class mcdf_rgm extends uvm_reg_block;
- `uvm_object_utils(mcdf_rgm)
- rand slv_en_reg slv_en;
- rand parity_err_clr_reg parity_err_clr;
- rand slv_id_reg slv_id;
- rand slv_len_reg slv_len;
- rand slv0_free_slot_reg slv0_free_slot;
- rand slv1_free_slot_reg slv1_free_slot;
- rand slv2_free_slot_reg slv2_free_slot;
- rand slv3_free_slot_reg slv3_free_slot;
- rand slv0_parity_err_reg slv0_parity_err;
- rand slv1_parity_err_reg slv1_parity_err;
- rand slv2_parity_err_reg slv2_parity_err;
- rand slv3_parity_err_reg slv3_parity_err;
- uvm_reg_map map;
- function new(string name = "mcdf_rgm");
- super.new(name, UVM_NO_COVERAGE);
- endfunction
- virtual function void build();
- slv_en = slv_en_reg::type_id::create("slv_en");
- slv_en.configure(this);
- slv_en.build();
- parity_err_clr = parity_err_clr_reg::type_id::create("parity_err_clr");
- parity_err_clr.configure(this);
- parity_err_clr.build();
- slv_id = slv_id_reg::type_id::create("slv_id");
- slv_id.configure(this);
- slv_id.build();
- slv_len = slv_len_reg::type_id::create("slv_len");
- slv_len.configure(this);
- slv_len.build();
- slv0_free_slot = slv0_free_slot_reg::type_id::create("slv0_free_slot");
- slv0_free_slot.configure(this);
- slv0_free_slot.build();
- slv1_free_slot = slv1_free_slot_reg::type_id::create("slv1_free_slot");
- slv1_free_slot.configure(this);
- slv1_free_slot.build();
- slv2_free_slot = slv2_free_slot_reg::type_id::create("slv2_free_slot");
- slv2_free_slot.configure(this);
- slv2_free_slot.build();
- slv3_free_slot = slv3_free_slot_reg::type_id::create("slv3_free_slot");
- slv3_free_slot.configure(this);
- slv3_free_slot.build();
- slv0_parity_err = slv0_parity_err_reg::type_id::create("slv0_parity_err");
- slv0_parity_err.configure(this);
- slv0_parity_err.build();
- slv1_parity_err = slv1_parity_err_reg::type_id::create("slv1_parity_err");
- slv1_parity_err.configure(this);
- slv1_parity_err.build();
- slv2_parity_err = slv2_parity_err_reg::type_id::create("slv2_parity_err");
- slv2_parity_err.configure(this);
- slv2_parity_err.build();
- slv3_parity_err = slv3_parity_err_reg::type_id::create("slv3_parity_err");
- slv3_parity_err.configure(this);
- slv3_parity_err.build();
- map = create_map("map", 'h0, 4, UVM_LITTLE_ENDIAN);
- map.add_reg(slv_en, 32'h00, "RW");
- map.add_reg(parity_err_clr, 32'h04, "RW");
- map.add_reg(slv_id, 32'h08, "RW");
- map.add_reg(slv_len, 32'h0C, "RW");
- map.add_reg(slv0_free_slot, 32'h80, "RO");
- map.add_reg(slv1_free_slot, 32'h84, "RO");
- map.add_reg(slv2_free_slot, 32'h88, "RO");
- map.add_reg(slv3_free_slot, 32'h8C, "RO");
- map.add_reg(slv0_parity_err, 32'h90, "RO");
- map.add_reg(slv1_parity_err, 32'h94, "RO");
- map.add_reg(slv2_parity_err, 32'h98, "RO");
- map.add_reg(slv3_parity_err, 32'h9C, "RO");
- //slv_en.add_hdl_path_slice("???", 0, 32);
- //parity_err_clr.add_hdl_path_slice("???", 0, 32);
- //slv_id.add_hdl_path_slice("???", 0, 32);
- //slv_len.add_hdl_path_slice("???", 0, 32);
- //slv0_free_slot.add_hdl_path_slice("???", 0, 32);
- //slv1_free_slot.add_hdl_path_slice("???", 0, 32);
- //slv2_free_slot.add_hdl_path_slice("???", 0, 32);
- //slv3_free_slot.add_hdl_path_slice("???", 0, 32);
- //slv0_parity_err.add_hdl_path_slice("???", 0, 32);
- //slv1_parity_err.add_hdl_path_slice("???", 0, 32);
- //slv2_parity_err.add_hdl_path_slice("???", 0, 32);
- //slv3_parity_err.add_hdl_path_slice("???", 0, 32);
- //add_hdl_path("???");
- lock_model();
- endfunction
- endclass