UVM实战--带有寄存器的加法器
一.整体的设计结构图
这里将DUT换成加法器,可以理解为之前UVM加法器加上寄存器,这里总线的功能不做修改,目的看代码的移植那些部分需要修改。
二.各个组件代码详解
2.1 DUT
module dut(
input clk,
input rst_n,
input bus_cmd_valid,//为1时表示数据有效,只持续一个时钟
input bus_op,//1时为写。0时为读
input [15:0] bus_addr,//地址
input [15:0] bus_wr_data,//读取的数据
output [15:0] bus_rd_data,//写入的数据input [7:0] a,
input [7:0] b,
input cin,
input enable,output [7:0] sum,
output enable1,
output cout,
reg invert
);//如果invert为1翻转,否则直接输出
always @(posedge clk) beginif(!rst_n) beginsum <= 8'b0;cout <= 1'b0;enable1 <= 1'b0;endelse if(invert) begin{cout,sum} <= ~a + ~b + ~cin;enable1 <= enable;endelse beginenable1 <= enable;{cout,sum} <= a + b + cin;end
endalways @(posedge clk) beginif(!rst_n) invert <= 1'b0;else if(bus_cmd_valid && bus_op) begincase(bus_addr)16'h9: begininvert <= bus_wr_data[0];enddefault: beginendendcaseend
endreg [15:0] bus_rd_data;
always @(posedge clk) beginif(!rst_n)bus_rd_data <= 16'b0;else if(bus_cmd_valid && !bus_op) begincase(bus_addr)16'h9: beginbus_rd_data <= {15'b0, invert};enddefault: beginbus_rd_data <= 16'b0; endendcaseend
endendmodule
2.2 bus_driver.sv
`ifndef BUS_DRIVER__SV
`define BUS_DRIVER__SV
class bus_driver extends uvm_driver#(bus_transaction);virtual bus_if vif;`uvm_component_utils(bus_driver)function new(string name = "bus_driver", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual bus_if)::get(this, "", "vif", vif))`uvm_fatal("bus_driver", "virtual interface must be set for vif!!!")endfunctionextern task run_phase(uvm_phase phase);extern task drive_one_pkt(bus_transaction tr);
endclasstask bus_driver::run_phase(uvm_phase phase);vif.bus_cmd_valid <= 1'b0;vif.bus_op <= 1'b0;vif.bus_addr <= 15'b0;vif.bus_wr_data <= 15'b0;while(!vif.rst_n)@(posedge vif.clk);while(1) beginseq_item_port.get_next_item(req);drive_one_pkt(req);seq_item_port.item_done();end
endtasktask bus_driver::drive_one_pkt(bus_transaction tr);`uvm_info("bus_driver", "begin to drive one pkt", UVM_LOW);repeat(1) @(posedge vif.clk);vif.bus_cmd_valid <= 1'b1;vif.bus_op <= ((tr.bus_op == BUS_RD) ? 0 : 1);vif.bus_addr = tr.addr;vif.bus_wr_data <= ((tr.bus_op == BUS_RD) ? 0 : tr.wr_data);@(posedge vif.clk);vif.bus_cmd_valid <= 1'b0;vif.bus_op <= 1'b0;vif.bus_addr <= 15'b0;vif.bus_wr_data <= 15'b0;@(posedge vif.clk);if(tr.bus_op == BUS_RD) begintr.rd_data = vif.bus_rd_data; //$display("@%0t, rd_data is %0h", $time, tr.rd_data);end//`uvm_info("bus_driver", "end drive one pkt", UVM_LOW);
endtask`endif
2.3 bus_sequencer.sv
`ifndef BUS_SEQUENCER__SV
`define BUS_SEQUENCER__SVclass bus_sequencer extends uvm_sequencer #(bus_transaction);function new(string name, uvm_component parent);super.new(name, parent);endfunction `uvm_component_utils(bus_sequencer)
endclass`endif
2.4 bus_monitor
`ifndef BUS_MONITOR__SV
`define BUS_MONITOR__SV
class bus_monitor extends uvm_monitor;virtual bus_if vif;uvm_analysis_port #(bus_transaction) ap;`uvm_component_utils(bus_monitor)function new(string name = "bus_monitor", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual bus_if)::get(this, "", "vif", vif))`uvm_fatal("bus_monitor", "virtual interface must be set for vif!!!")ap = new("ap", this);endfunctionextern task main_phase(uvm_phase phase);extern task collect_one_pkt(bus_transaction tr);
endclasstask bus_monitor::main_phase(uvm_phase phase);bus_transaction tr;while(1) begintr = new("tr");collect_one_pkt(tr);ap.write(tr);end
endtasktask bus_monitor::collect_one_pkt(bus_transaction tr);while(1) begin@(posedge vif.clk);if(vif.bus_cmd_valid) break;endtr.bus_op = ((vif.bus_op == 0) ? BUS_RD : BUS_WR);tr.addr = vif.bus_addr;tr.wr_data = vif.bus_wr_data;@(posedge vif.clk);tr.rd_data = vif.bus_rd_data;`uvm_info("bus_monitor", "end collect one pkt", UVM_LOW);
endtask`endif
2.5 bus_agent.sv
`ifndef BUS_AGENT__SV
`define BUS_AGENT__SVclass bus_agent extends uvm_agent ;bus_sequencer sqr;bus_driver drv;bus_monitor mon;uvm_analysis_port #(bus_transaction) ap;function new(string name, uvm_component parent);super.new(name, parent);endfunction extern virtual function void build_phase(uvm_phase phase);extern virtual function void connect_phase(uvm_phase phase);`uvm_component_utils(bus_agent)
endclass function void bus_agent::build_phase(uvm_phase phase);super.build_phase(phase);if (is_active == UVM_ACTIVE) beginsqr = bus_sequencer::type_id::create("sqr", this);drv = bus_driver::type_id::create("drv", this);endmon = bus_monitor::type_id::create("mon", this);
endfunction function void bus_agent::connect_phase(uvm_phase phase);super.connect_phase(phase);if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);endap = mon.ap;
endfunction`endif
2.6 bus_transaction.sv
`ifndef BUS_TRANSACTION__SV
`define BUS_TRANSACTION__SVtypedef enum{BUS_RD, BUS_WR} bus_op_e;class bus_transaction extends uvm_sequence_item;rand bit[15:0] rd_data;rand bit[15:0] wr_data;rand bit[15:0] addr;rand bus_op_e bus_op;`uvm_object_utils_begin(bus_transaction)`uvm_field_int(rd_data, UVM_ALL_ON)`uvm_field_int(wr_data, UVM_ALL_ON)`uvm_field_int(addr , UVM_ALL_ON)`uvm_field_enum(bus_op_e, bus_op, UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "bus_transaction");super.new();endfunctionendclass
`endif
2.7 bus_if
`ifndef BUS_IF__SV
`define BUS_IF__SVinterface bus_if(input clk, input rst_n);logic bus_cmd_valid;logic bus_op;logic [15:0] bus_addr;logic [15:0] bus_wr_data;logic [15:0] bus_rd_data;endinterface`endif
2.8 my_if
`ifndef MY_IF__SV
`define MY_IF__SVinterface my_if(input clk, input rst_n);logic [7:0] a;logic [7:0] b;logic cin;logic enable;wire enable1;wire [7:0] sum;wire cout;endinterface
`endif
2.9 my_driver
`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;virtual my_if vif;`uvm_component_utils(my_driver)function new(string name = "my_driver",uvm_component parent = null);super.new(name,parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))`uvm_fatal("my_driver","virtual interface must be set for vif!!!")endfunctionextern task mian_phase(uvm_phase phase);extern task drive_one_pkt(my_transaction_i tr);
endclasstask my_driver::mian_phase(uvm_phase phase);vif.a <= 8'b0;vif.b <= 8,b0;vif.cin <= 1'b0;vif.enable <= 1'b0;while(!vif.rst_n)begin@(posedge vif.clk);endwhile(1)beginseq_item_port.get_next_item(req);drive_one_pkt(req);seq_item_port.item_done();end
endtasktask my_driver::drive_one_pkt(my_transcation_i tr);uvm_info("my_driver","begin to dirve one pkt",UVM_LOW);@(posedge vif.clk);vif.a <= tr.a;vif.b <= tr.b;vif.cin <= tr.cin;vif.enable <= 1'b1;@(posedge vif.clk)vif.enable <= 1'b0;`uvm_info("my_driver","end to drive one pkt",UVM_LOW);
endtask
`endif
2.10 my_transaction_i
`ifdenf MY_TRANSACTION_I__SV
`define MY_TRANSACTION_I__SVclass my_transaction_i extends uvm_sequence_item;rand bit [7:0] a;rand bit [7:0] b;rand bit cin;`uvm_object_utils_begin(my_transaction_i)`uvm_field_int(a,UVM_ALL_ON)`uvm_field_int(b,UVM_ALL_ON)`uvm_field_int(cin,UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "my_transaction_i");super.new();endfunction
endclass
`endif
2.11 my_transaction_o
`idndef MY_TRANSACTION_O__SV
`define MY_TRANSACTION_O__SVclass my_transaction_o extends uvm_sequence_item;bit [7:0] sum;bit cout;function new(string name = "my_transaction_o")super.new();endfunction
endclass
`endif
2.12 my_sequencer
`ifndef MY_SEQUENCER__SV
`define MY_SEQUENCER__SVclass my_sequencer extends uvm_sequencer #(my_transaction_i);function new(string name,uvm_component parent);super.new(name,parent);endfunction`uvm_component_utils(my_sequencer)
endclass
`endif
2.13 my_monitor_i
`ifndef MY_MONITOR_I__SV
`define MY_MONITOR_I__SVclass my_monitor_i extends uvm_monitor;virtual my_if vif;uvm_analysis_port #(my_transaction_i) ap;`uvm_component_utils(my_monitor_i)function new(string name = "monitor_i",uvm_component parent = null);super.new(name,parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")ap = new("ap",this);endfunctionextern task main_phase(uvm_phase phase);extern task drive_one_pkt(my_transaction_i tr);
endclasstask my_monitor::main_phase(uvm_phase phase);my_transaction_i tr;while(1) begintr.new("tr");collect_one_pkt(tr);ap.write(tr);end
endtasktask my_monitor::collcet_one_pkt(my_transaction_i tr);
while(1) begin@(posedge vif.clk);if(vif.enable) break;
end`uvm_info("my_monitor","begin to collcet one pkt",UVM_LOW); @(posedge vif.clk);tr.a <= vif.a;tr.b <= vif.b;tr.cin <= vif.cin;`uvm_info("my_monitor","end to collcet one pkt",UVM_LOW);
endtask
`endif
2.14 my_monitor_o
`ifndef MY_MONITOR_O__SV
`define MY_MONITOR_O__SV
class my_monitor_o extends uvm_monitorvirtual my_if vif;uvm_analysis_port #(my_transaction_o) ap;`uvm_component_port #(my_transaction_o) ap;function new(string name = "my_monitor_o",uvm_component parent = null);super.new(name,parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")ap = new("ap",this);endfunctionextern task main_phase(uvm_phase phase);extern task collcet_one_pkt(my_transaction_i tr);
endclasstask my_monitor::main_phase (uvm_phase phase);my_transaction_o tr;while(1) begintr = new("tr")collcet_one_pkt(tr);ap.write(tr);end
endtasktask my_monitor::collcet_one_pkt(my_transction_o tr);
while(1) begin@(posedge vif.clk)if(vif.enable1) break;
end`uvm_info("my_monitor_o","begin to collcet one pkt",UVM_LOW);@(posedge vif.clk)tr.sum <= vif.sum;tr.cout <= vif.cout;`uvm_info("my_monitor_o","end to collcet one pkt",UVM_ALL);
endtask
`endif
2.15 my_agent_i
`ifndef MY_AGENT_I__SV
`define MY_AGENT_I__SVclass my_agent_i extends uvm_agent;my_sequencer sqr;my_driver drv;my_monitor_i mon_i;`uvm_analysis_port #(my_transaction_i) ap;function new(string name,uvm_component parent);super.new(name,parent);endfunctionextern virtual function void build_phase(uvm_phase phase);extern virtual function void conncet_phase(uvm_phase phase);`uvm_component_utils(my_agent_i)
endclassfunction void my_agent_i::build_phase(uvm_phase phase);super.build_phase(phase);sqr = my_sequencer::type_id::create("sqr",this);drv = my_driver::type_id::create("drv",this);mon_i = my_monitor_i::type_id::create("mon_i",this);
endfunctionfunction void my_agent_i::conncet_phase(uvm_phase phase);super.conncet_phase(phase);drv_seq_item_port.conncet(sqr.seq_item_export);ap = mon.ap;
endfunction
`endif
2.16 my_agent_o
`ifndef MY_AGENT_O__SV
`define MY_AGENT_O__SVclass my_agent_o extends uvm_agent;my_sequencer sqr;my_driver drv;my_monitor_o mon_o;`uvm_analysis_port #(my_transaction_o) ap;function new(string name,uvm_component parent);super.new(name,parent);endfunctionextern virtual function void build_phase(uvm_phase phase);extern virtual function void conncet_phase(uvm_phase phase);`uvm_component_utils(my_agent_o)
endclassfunction void my_agent_o::build_phase(uvm_phase phase);super.build_phase(phase);mon_o = my_monitor_o::type_id::create("mon",this);
endfunctionfunction void my_agent_o::conncet_phase(uvm_phase phase);super.conncet_phase(phase);ap = mon.ap;
endfunction
`endif
2.17 my_scoreboard
`ifndef MY_SCOREBOARD__SV
`define MY_SCOREBOARD__SV
class my_scoreboard extends uvm_scoreboard;my_transaction expect_queue[$];uvm_blocking_get_port #(my_transaction) exp_port;uvm_blocking_get_port #(my_transaction) act_port;`uvm_component_utils(my_scoreboard)extern function new(string name, uvm_component parent = null);extern virtual function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclass function my_scoreboard::new(string name, uvm_component parent = null);super.new(name, parent);
endfunction function void my_scoreboard::build_phase(uvm_phase phase);super.build_phase(phase);exp_port = new("exp_port", this);act_port = new("act_port", this);
endfunction task my_scoreboard::main_phase(uvm_phase phase);my_transaction get_expect, get_actual, tmp_tran;bit result;super.main_phase(phase);fork while (1) beginexp_port.get(get_expect);expect_queue.push_back(get_expect);endwhile (1) beginact_port.get(get_actual);if(expect_queue.size() > 0) begintmp_tran = expect_queue.pop_front();result = get_actual.compare(tmp_tran);if(result) begin `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);endelse begin`uvm_error("my_scoreboard", "Compare FAILED");$display("the expect pkt is");tmp_tran.print();$display("the actual pkt is");get_actual.print();endendelse begin`uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");$display("the unexpected pkt is");get_actual.print();end endjoin
endtask
`endif
2.18 my_env
`ifndef MY_ENV__SV
`define MY_ENV__SVclass my_env extends uvm_env;my_agent_i i_agt;my_agent_o o_agt;bus_agent bus_agt;my_model mdl;my_scoreboard scb;reg_model p_rm;uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;function new(string name = "my_env", uvm_component parent);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);i_agt = my_agent::type_id::create("i_agt", this);o_agt = my_agent::type_id::create("o_agt", this);bus_agt = bus_agent::type_id::create("bus_agt", this);bus_agt.is_active = UVM_ACTIVE;mdl = my_model::type_id::create("mdl", this);scb = my_scoreboard::type_id::create("scb", this);agt_scb_fifo = new("agt_scb_fifo", this);agt_mdl_fifo = new("agt_mdl_fifo", this);mdl_scb_fifo = new("mdl_scb_fifo", this);endfunctionextern virtual function void connect_phase(uvm_phase phase);`uvm_component_utils(my_env)
endclassfunction void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);i_agt.ap.connect(agt_mdl_fifo.analysis_export);mdl.port.connect(agt_mdl_fifo.blocking_get_export);mdl.ap.connect(mdl_scb_fifo.analysis_export);scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);o_agt.ap.connect(agt_scb_fifo.analysis_export);scb.act_port.connect(agt_scb_fifo.blocking_get_export); mdl.p_rm = this.p_rm;
endfunction`endif
2.19 my_model
`ifndef MY_MODEL__SV
`define MY_MODEL__SVclass my_model extends uvm_component;uvm_blocking_get_port #(my_transaction_i) port;uvm_analysis_port #(my_transaction_o) ap;extern function new(string name,uvm_component parent);extern function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);extern virtual function void invert_tr(my_transaction_o tr2);`uvm_component_utils(my_model)
endclassfunction my_model::new(string name,uvm_component parent);super.new(name,parent);
endfunctionfunction void my_model::build_phase(uvm_phase phase);super.build_phase(phase);port = new("port",this);ap = new("ap",this);
endfunctionfunction void my_model::invert_tr(my_transaction_o tr2);tr2.sum = tr2.sum ^ 8'hFF;tr2.cout = tr2.cout ^ 1'b1;
endfunction
task my_model::main_phase(uvm_phase phase);my_transaction_i tr;my_transaction_o tr2;uvm_state_e states;uvm_reg_data_t value;bit [8:0] sum_total;super.main_phase(phase);p_rm.invert.read(status,value,UVM_FRONTDOOR);while(1)beginport.get(tr);tr2 = new("tr2");sum_total = tr.a+tr.b+tr.cin;tr2.sum = sum_total[7:0];tr2.cout = sum_total[8];is(value)invert_tr(tr2);`uvm_info("my_model", "get transactions, add and print it:", UVM_LOW)tr2.print();ap.write(tr2);end
endtask
`endif
2.20 my_env
`ifndef MY_ENV__SV
`define MY_ENV__SVclass my_env extends uvm_env;my_agent_i i_agt;my_agent_o o_agt;bus_agent bus_agt;my_model mdl;my_scoreboard scb;reg_model p_rm;uvm_tlm_analysis_fifo #(my_transaction_o) agt_scb_fifo;uvm_tlm_analysis_fifo #(my_transaction_i) agt_mdl_fifo;uvm_tlm_analysis_fifo #(my_transaction_o) mdl_scb_fifo;function new(string name = "my_env", uvm_component parent);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);i_agt = my_agent::type_id::create("i_agt", this);o_agt = my_agent::type_id::create("o_agt", this);bus_agt = bus_agent::type_id::create("bus_agt", this);bus_agt.is_active = UVM_ACTIVE;mdl = my_model::type_id::create("mdl", this);scb = my_scoreboard::type_id::create("scb", this);agt_scb_fifo = new("agt_scb_fifo", this);agt_mdl_fifo = new("agt_mdl_fifo", this);mdl_scb_fifo = new("mdl_scb_fifo", this);endfunctionextern virtual function void connect_phase(uvm_phase phase);`uvm_component_utils(my_env)
endclassfunction void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);i_agt.ap.connect(agt_mdl_fifo.analysis_export);mdl.port.connect(agt_mdl_fifo.blocking_get_export);mdl.ap.connect(mdl_scb_fifo.analysis_export);scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);o_agt.ap.connect(agt_scb_fifo.analysis_export);scb.act_port.connect(agt_scb_fifo.blocking_get_export); mdl.p_rm = this.p_rm;
endfunction`endif
2.21 base_test
`ifndef BASE_TEST__SV
`define BASE_TEST__SVclass base_test extends uvm_test;my_env env;my_vsqr v_sqr;//(2)成员变量的理解reg_model rm;my_adapter reg_sqr_adapter;function new(string name = "base_test", uvm_component parent = null);super.new(name,parent);endfunctionextern virtual function void build_phase(uvm_phase phase);extern virtual function void connect_phase(uvm_phase phase);extern virtual function void report_phase(uvm_phase phase);`uvm_component_utils(base_test)
endclassfunction void base_test::build_phase(uvm_phase phase);super.build_phase(phase);env = my_env::type_id::create("env", this); v_sqr = my_vsqr::type_id::create("v_sqr", this);rm = reg_model::type_id::create("rm", this);rm.configure(null, "");rm.build();rm.lock_model();rm.reset();rm.set_hdl_path_root("top_tb.my_dut");reg_sqr_adapter = new("reg_sqr_adapter");env.p_rm = this.rm;
endfunctionfunction void base_test::connect_phase(uvm_phase phase);super.connect_phase(phase);v_sqr.p_my_sqr = env.i_agt.sqr;v_sqr.p_bus_sqr = env.bus_agt.sqr;v_sqr.p_rm = this.rm;rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);rm.default_map.set_auto_predict(1);
endfunctionfunction void base_test::report_phase(uvm_phase phase);uvm_report_server server;int err_num;super.report_phase(phase);server = get_report_server();err_num = server.get_severity_count(UVM_ERROR);if (err_num != 0) begin$display("TEST CASE FAILED");endelse begin$display("TEST CASE PASSED");end
endfunction`endif
2.22 reg_model
`ifndef REG_MODEL__SV
`define REG_MODEL__SV
//uvm_reg是比较小的单位,一个寄存器中至少包含一个uvm_reg_field
class reg_invert extends uvm_reg;//uvm_reg_filed是寄存器模型中的最小单位rand uvm_reg_field reg_data;//build的理解virtual function void build();reg_data = uvm_reg_field::type_id::create("reg_data");// parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible//(4)configure的参数理解reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);endfunction`uvm_object_utils(reg_invert)function new(input string name="reg_invert");//parameter: name, size, has_coverage//(3)new函数的理解super.new(name, 16, UVM_NO_COVERAGE);endfunction
endclassclass reg_counter extends uvm_reg;rand uvm_reg_field reg_data;virtual function void build();reg_data = uvm_reg_field::type_id::create("reg_data");// parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessiblereg_data.configure(this, 32, 0, "W1C", 1, 0, 1, 1, 0);endfunction`uvm_object_utils(reg_counter)function new(input string name="reg_counter");//parameter: name, size, has_coveragesuper.new(name, 32, UVM_NO_COVERAGE);endfunction
endclass//uvm_reg_block它是一个较大的单位,在其中可以加入很多的uvm_reg,也可以加入其他的uvm_reg_block
class reg_model extends uvm_reg_block;rand reg_invert invert;rand reg_counter counter;virtual function void build();//(5)uvm_reg_mapdefault_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);//(6)实例化invert并调用invert.configure函数invert = reg_invert::type_id::create("invert", , get_full_name());invert.configure(this, null, "invert");invert.build();//(7)default_mapdefault_map.add_reg(invert, 'h9, "RW");counter= reg_counter::type_id::create("counter", , get_full_name());counter.configure(this, null, "counter");counter.build();default_map.add_reg(counter, 'h5, "RW");endfunction`uvm_object_utils(reg_model)function new(input string name="reg_model");super.new(name, UVM_NO_COVERAGE);endfunction endclass
`endif
2.23 my_adapter
`ifndef MY_ADAPTER__SV
`define MY_ADAPTER__SV
//(1)adapter的作用
class my_adapter extends uvm_reg_adapter;string tID = get_type_name();`uvm_object_utils(my_adapter)function new(string name="my_adapter");super.new(name);endfunction : new//reg2bus,其作用为寄存器模型通过sequence发出的uvm_reg_bus_op型的变量转换成bus_sequencer能够接收的形式function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);bus_transaction tr;tr = new("tr"); tr.addr = rw.addr;tr.bus_op = (rw.kind == UVM_READ) ? BUS_RD: BUS_WR;if (tr.bus_op == BUS_WR)tr.wr_data = rw.data; return tr;endfunction : reg2bus//bus2reg,其作用为当监测到总线上有操作时,它将收集来的transaction转换成寄存器模型能够接受的形式,以便寄存器模型能够更新相应的寄存器的值。function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);bus_transaction tr;if(!$cast(tr, bus_item)) begin`uvm_fatal(tID,"Provided bus_item is not of the correct type. Expecting bus_transaction")return;endrw.kind = (tr.bus_op == BUS_RD) ? UVM_READ : UVM_WRITE;rw.addr = tr.addr;rw.byte_en = 'h3;rw.data = (tr.bus_op == BUS_RD) ? tr.rd_data : tr.wr_data;rw.status = UVM_IS_OK;endfunction : bus2regendclass : my_adapter
`endif
2.24 my_vsqr
`ifndef MY_VSQR__SV
`define MY_VSQR__SVclass my_vsqr extends uvm_sequencer;my_sequencer p_my_sqr;bus_sequencer p_bus_sqr;reg_model p_rm;function new(string name, uvm_component parent);super.new(name, parent);endfunction `uvm_component_utils(my_vsqr)
endclass`endif
2.25 my_case0
`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction_i);my_transaction_i m_trans;function new(string name= "case0_sequence");super.new(name);endfunction virtual task body();repeat (10) begin`uvm_do(m_trans)endendtask`uvm_object_utils(case0_sequence)
endclassclass case0_cfg_vseq extends uvm_sequence;`uvm_object_utils(case0_cfg_vseq)`uvm_declare_p_sequencer(my_vsqr)function new(string name= "case0_cfg_vseq");super.new(name);endfunction virtual task body();uvm_status_e status;uvm_reg_data_t value;bit[31:0] counter;uvm_reg_block blks[$];reg_model p_rm;if(starting_phase != null) starting_phase.raise_objection(this);uvm_reg_block::get_root_blocks(blks);if(blks.size() == 0)`uvm_fatal("case0_cfg_vseq", "can't find root blocks")else beginif(!$cast(p_rm, blks[0]))`uvm_fatal("case0_cfg_vseq", "can't cast to reg_model")endp_rm.invert.read(status, value, UVM_FRONTDOOR);`uvm_info("case0_cfg_vseq", $sformatf("invert's initial value is %0h", value), UVM_LOW)p_rm.invert.write(status, 1, UVM_FRONTDOOR);p_rm.invert.read(status, value, UVM_FRONTDOOR);`uvm_info("case0_cfg_vseq", $sformatf("after set, invert's value is %0h", value), UVM_LOW)p_rm.counter.read(status, value, UVM_FRONTDOOR);counter = value;`uvm_info("case0_cfg_vseq", $sformatf("counter's initial value(FRONTDOOR) is %0h", counter), UVM_LOW)p_rm.counter.poke(status, 32'hFFFD);p_rm.counter.read(status, value, UVM_FRONTDOOR);counter = value;`uvm_info("case0_cfg_vseq", $sformatf("after poke, counter's value(FRONTDOOR) is %0h", counter), UVM_LOW)p_rm.counter.peek(status, value);counter = value;`uvm_info("case0_cfg_vseq", $sformatf("after poke, counter's value(BACKDOOR) is %0h", counter), UVM_LOW)if(starting_phase != null) starting_phase.drop_objection(this);endtaskendclassclass case0_vseq extends uvm_sequence;`uvm_object_utils(case0_vseq)`uvm_declare_p_sequencer(my_vsqr)function new(string name= "case0_vseq");super.new(name);endfunction virtual task body();case0_sequence dseq;uvm_status_e status;uvm_reg_data_t value;if(starting_phase != null) starting_phase.raise_objection(this);#10000;dseq = case0_sequence::type_id::create("dseq");dseq.start(p_sequencer.p_my_sqr);if(starting_phase != null) starting_phase.drop_objection(this);endtaskendclassclass my_case0 extends base_test;function new(string name = "my_case0", uvm_component parent = null);super.new(name,parent);endfunction extern virtual function void build_phase(uvm_phase phase); `uvm_component_utils(my_case0)
endclassfunction void my_case0::build_phase(uvm_phase phase);super.build_phase(phase);uvm_config_db#(uvm_object_wrapper)::set(this, "v_sqr.configure_phase", "default_sequence", case0_cfg_vseq::type_id::get());uvm_config_db#(uvm_object_wrapper)::set(this, "v_sqr.main_phase", "default_sequence", case0_vseq::type_id::get());
endfunction`endif
2.26 top_tb
`timescale 1ns/1ps
`include "uvm_macros.svh" //UVM中的一个文件,包含众多的宏定义import uvm_pkg::*; //将整个uvm_pkg导入到验证平台中,编译器在编译my_driver.sv文件时才能认识uvm_driver其中的uvm_driver等类名
`include "my_if.sv"
`include "bus_if.sv"
`include "bus_transaction.sv"
`include "bus_agent.sv"
`include "bus_driver.sv"
`include "bus_monitor.sv"
`include "bus_sequencer.sv"
`include "my_transaction_i.sv"
`include "my_transaction_o.sv"
`include "my_sequencer.sv"
`include "my_driver.sv"
`include "my_monitor_i.sv"
`include "my_monitor_o.sv"
`include "my_agent_i.sv"
`include "my_agent_o.sv"
`include "my_model.sv"
`include "my_scoreboard.sv"
`include "my_env.sv"
`include "base_test.sv"
`include "my_case0.sv"
`include "reg_model.sv"
`include "my_adapter.sv"
`include "my_vsqr.sv"module top_tb;reg clk;
reg rst_n;
reg [7:0] a;
reg [7:0] b;
reg enable;
reg cin;wire enable1;
wire cout;
wire [7:0] sum; my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);
bus_if b_if(clk,rst_n);dut my_dut(.clk(clk), //例化DUT.rst_n(rst_n),.a(input_if.a),.b(input_if.b),.cin(input_if.cin),.enable(input_if.enable),.enable1(output_if.enable1),.cout(output_if.cout),.sum(output_if.sum),.bus_cmd_valid (b_if.bus_cmd_valid),.bus_op (b_if.bus_op),.bus_addr (b_if.bus_addr),.bus_wr_data (b_if.bus_wr_data),.bus_rd_data (b_if.bus_rd_data));initial begin clk = 0;forever begin#100 clk = ~clk;end
endinitial beginrst_n = 1'b0;#1000;rst_n = 1'b1;
endinitial begin run_test();
endinitial begininput_if.a = 8'b00000000;input_if.b = 8'b00000000;input_if.cin = 1'b0;input_if.enable = 1'b1;
endinitial begin//(1) uvm_config_db::setuvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);uvm_config_db#(virtual bus_if)::set(null, "uvm_test_top.env.bus_agt.drv", "vif", bus_if);uvm_config_db#(virtual bus_if)::set(null, "uvm_test_top.env.bus_agt.mon", "vif", bus_if);
endendmodule
相关文章:

UVM实战--带有寄存器的加法器
一.整体的设计结构图 这里将DUT换成加法器,可以理解为之前UVM加法器加上寄存器,这里总线的功能不做修改,目的看代码的移植那些部分需要修改。 二.各个组件代码详解 2.1 DUT module dut( input clk, input rst_n, input…...

笔记--学习mini3d代码
主要是记录学习mini3d代码时,查的资料; 从github下载的代码: GitHub - skywind3000/mini3d: 3D Software Renderer in 700 Lines !!3D Software Renderer in 700 Lines !! Contribute to skywind3000/mini3d development by creating an a…...

图片服务器
文章目录一、项目简介二、功能及场景三、业务设计四、数据库设计准备图片表准备实体类五、API设计常用功能封装文件上传文件上传获取图片列表接口获取图片内容删除图片接口六、项目优化七、测试自动化测试测试用例一、项目简介 图片服务器:解决项目中插入图片的问题…...

【JAVA程序设计】【C00110】基于SSM(非maven)的车辆维修管理系统
基于SSM(非maven)的车辆维修管理系统项目简介项目获取开发环境项目技术运行截图项目简介 基于ssm框架非maven开发的车辆维修管理系统共分为三个角色:管理员、用户 管理员角色包含以下功能: 查看用户、添加用户、查看车辆信息、故…...
微积分小课堂:用动态的眼光去找问题的最优解(最大值/最小值)【中学里的解题技巧】
文章目录 引言I 最优化问题1.1 不同形式的最优化1.2 用动态的眼光去找问题的最优解引言 把比较数大小的问题,变成了寻找函数变化拐点的问题,将这两个问题等同起来,需要发明一种工具,叫做导数。有了导数这个工具,求最大值问题就变成了解方程的问题。 用变化的眼光找到最优…...
网络爬虫和相关工具
在理想的状态下,所有ICP(Internet Content Provider)都应该为自己的网站提供API接口来共享它们允许其他程序获取的数据,在这种情况下爬虫就不是必需品,国内比较有名的电商平台(如淘宝、京东等)、…...

OSSFs挂载工具简介
OSSFs挂载工具 OSSFs挂载工具简介 ossfs允许您在Linux系统中将对象存储OSS的存储空间(Bucket)挂载到本地文件系统。挂载完成后,您能够像操作本地文件一样操作OSS的对象(Object),从而实现数据共享。 …...

Spring 容器创建初始化,获取bean流程分析
Spring 容器创建初始化,获取bean流程分析 Spring 容器创建初始化 流程分析 1、首先读取bean.xml 文件 2、扫描指定的包 com.hspedu.spring.component 2.1、扫描包,得到bean的class对象,排除包下不是bean的 2.2、扫描将bean信息封装BeanDef…...

无聊小知识.03 Springboot starter配置自动提示
1、前言Springboot项目配置properties或yaml文件时候,会有很多spring相关的配置提示。这个是如何实现的?如果我们自己的配置属性,能否也自动提示?2、Springboot配置自动提示其实IDE是通过读取配置信息的元数据而实现自动提示的。S…...
2023-03-03 mysql-join类别-分析
目录 摘要: mysql版本: DDL: 表结构: 插入数据: JOIN: 一. SELECT 二. INNER JOIN...

Saleen 系列来袭!
由 Ghostopunch 创作👻🥊 Ghostpunch 将 Saleen Automotive 带入 The Sandbox 元宇宙! 是 Saleen Automotive 于 1984 年由汽车界的梦想家 Steve Saleen 创立,目标是将经过比赛验证的性能带入大街小巷和元宇宙……😉 5…...
如何优雅地处理Java中的null值?使用Optional类来实现!
当我们在Java编程时,经常会遇到处理null值的问题。在Java 8中,引入了一个Optional类来解决这个问题。Optional类可以看作是一个容器,用于包装一个可能为null的值。它提供了一些方便的方法,以优雅地处理null值的情况。 下面我将详…...

巾帼绽芬芳 一起向未来(中篇)
编者按:为了隆重纪念纪念“三八”国际妇女节113周年,快来与你全方位、多层次分享交流“三八”国际妇女节的前世今生。分上篇(节日简介、节日发展和节日意义)、中篇(节日活动宗旨和世界各国庆祝方式)和下篇&…...
espnet training
from:ESPnet2 — ESPnet 202301 documentation from :Change the configuration for training — ESPnet 202301 documentation 训练完之后微调的命令: ./run.sh --stage 11 --ngpu 1 --asr_args "--max_epoch 205 --optim_conf lr=0.1 --resume true" --asr_exp…...

qsort函数的应用以及模拟实现
前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍库函数qsort函数的模拟实现和应用 金句分享: ✨追…...

【iobit 软件】家族系列 - 正版激活码
装机必备iobit系列软件 - 激活码获取看最后 第一款、Advanced SystemCare 16 您需要的人工智能驱动的PC优化器,以释放磁盘空间,加速PC并保护在线隐私。 功能特点: 1. 系统清理与优化:通过清除系统垃圾文件、注册表信息、无用文…...

ACM-大一训练第三周(Floyd算法+并查集算法专题训练)
🚀write in front🚀 📝个人主页:认真写博客的夏目浅石.CSDN 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝 📣系列专栏:ACM周训练题目合集.CSDN 💬总结:…...

taobao.item.sku.update( 更新SKU信息 )
¥开放平台免费API必须用户授权 *更新一个sku的数据 *需要更新的sku通过属性properties进行匹配查找 *商品的数量和价格必须大于等于0 *sku记录会更新到指定的num_iid对应的商品中 *num_iid对应的商品必须属于当前的会话用户 公共参数 请求地址: HTTP地址 http://gw.…...

ros2创建一个工程
第一步:创建src目录 $ mkdir ros2-demo $ cd ros2-demo/ $ mkdir src $ cd src/第二步:创建功能包cd src$ ros2 pkg create --build-type ament_cmake ros2_demo --dependencies rclcpp std_msgsros2 pkg create --build-type ament_python learning_pkg…...

【力扣】stack容器的探索之有效的括号
作者:狮子也疯狂 专栏:《算法详解》 愿你生如夏花之绚烂,幸运永远与你相伴,疯狂常在。 目录一. 🦁 Stack容器的来历1.1 操作栈的方法二. 🦁 Stack的使用2.1 题目2.2 分析2.3 详细算法实现2.4 力扣AC截图三…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...