I2C学习笔记——00apb_tb、mst_seq_lib、test(env、test_sequence、test)

news/2024/11/17 22:22:27/

apb_tb:tb是在dut侧;

        导入tests、if文件;设定周期、复位;例化接口,将接口config_db到uvm_test_top.env.mst和slv中;

`timescale 1ps/1ps
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "lvc_apb_tests.svh"
`include "lvc_apb_if.sv"
module lvc_apb_tb;bit clk, rstn;initial beginforkbegin forever #5ns clk = !clk;endbegin#100ns;rstn <= 1'b1;#100ns;rstn <= 1'b0;#100ns;rstn <= 1'b1;endjoin_noneendlvc_apb_if intf(clk, rstn);initial beginuvm_config_db#(virtual lvc_apb_if)::set(uvm_root::get(), "uvm_test_top.env.mst", "vif", intf);uvm_config_db#(virtual lvc_apb_if)::set(uvm_root::get(), "uvm_test_top.env.slv", "vif", intf);run_test("lvc_apb_single_transaction_test");endendmodule

apb_master_seq_lib:        

        base_sequence extends uvm_sequence #(lvc_apb_transfer): new();

        single_write:两个随机变量addr、data和表示状态的trans_status;body()中`uvm_do_with有约束的随机发送→get_response→将rsp返回的状态给trans_status;

        single_read:`uvm_do_with状态改为READ,最后将rsp返回的data给data变量;

        write_read:增加了变量idle_cycles,body()中两个`uvm_do_with;

        burst_write:变量data变成data[ ]数组,软约束随机data的size和值;`uvm_do_with嵌入循环中地址进行移位和发送data;判断rsp返回的状态;

        burst_read:uvm_do_with嵌入循环中地址进行移位,每次返回rsp中的data不断存入data[ ];判断rsp返回的状态;

`ifndef LVC_APB_MASTER_SEQ_LIB_SV
`define LVC_APB_MASTER_SEQ_LIB_SV//------------------------------------------------------------------------------
// SEQUENCE: default
//------------------------------------------------------------------------------
typedef class lvc_apb_transfer;
typedef class lvc_apb_master_sequencer;class lvc_apb_master_base_sequence extends uvm_sequence #(lvc_apb_transfer);`uvm_object_utils(lvc_apb_master_base_sequence)    function new(string name=""); super.new(name);endfunction : newendclass : lvc_apb_master_base_sequence // USER: Add your sequences hereclass lvc_apb_master_single_write_sequence extends lvc_apb_master_base_sequence;rand bit [31:0]      addr;rand bit [31:0]      data;lvc_apb_trans_status     trans_status;`uvm_object_utils(lvc_apb_master_single_write_sequence)    function new(string name=""); super.new(name);endfunction : newvirtual task body();`uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)`uvm_do_with(req, {trans_kind == WRITE; addr == local::addr; data == local::data;})get_response(rsp);trans_status = rsp.trans_status;`uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)endtask: bodyendclass: lvc_apb_master_single_write_sequenceclass lvc_apb_master_single_read_sequence extends lvc_apb_master_base_sequence;rand bit [31:0]      addr;rand bit [31:0]      data;lvc_apb_trans_status     trans_status;`uvm_object_utils(lvc_apb_master_single_read_sequence)    function new(string name=""); super.new(name);endfunction : newvirtual task body();`uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)`uvm_do_with(req, {trans_kind == READ; addr == local::addr;})get_response(rsp);trans_status = rsp.trans_status;data = rsp.data;`uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)endtask: bodyendclass: lvc_apb_master_single_read_sequenceclass lvc_apb_master_write_read_sequence extends lvc_apb_master_base_sequence;rand bit [31:0]    addr;rand bit [31:0]    data;rand int           idle_cycles; lvc_apb_trans_status     trans_status;constraint cstr{idle_cycles == 0;}`uvm_object_utils(lvc_apb_master_write_read_sequence)    function new(string name=""); super.new(name);endfunction : newvirtual task body();`uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)`uvm_do_with(req,  {trans_kind == WRITE; addr == local::addr; data == local::data;idle_cycles == local::idle_cycles;})get_response(rsp);`uvm_do_with(req, {trans_kind == READ; addr == local::addr;})get_response(rsp);data = rsp.data;trans_status = rsp.trans_status;`uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)endtask: bodyendclass: lvc_apb_master_write_read_sequenceclass lvc_apb_master_burst_write_sequence extends lvc_apb_master_base_sequence;rand bit [31:0]      addr;rand bit [31:0]      data[];lvc_apb_trans_status     trans_status;constraint cstr{soft data.size() inside {4, 8, 16, 32};foreach(data[i]) soft data[i] == addr + (i << 2);}`uvm_object_utils(lvc_apb_master_burst_write_sequence)    function new(string name=""); super.new(name);endfunction : newvirtual task body();`uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)trans_status = OK;foreach(data[i]) begin`uvm_do_with(req, {trans_kind == WRITE; addr == local::addr + (i<<2); data == local::data[i];idle_cycles == 0;})get_response(rsp);end`uvm_do_with(req, {trans_kind == IDLE;})get_response(rsp);trans_status = rsp.trans_status == ERROR ? ERROR : trans_status;`uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)endtask: body
endclass: lvc_apb_master_burst_write_sequenceclass lvc_apb_master_burst_read_sequence extends lvc_apb_master_base_sequence;rand bit [31:0]      addr;rand bit [31:0]      data[];lvc_apb_trans_status     trans_status;constraint cstr{soft data.size() inside {4, 8, 16, 32};}`uvm_object_utils(lvc_apb_master_burst_read_sequence)function new(string name=""); super.new(name);endfunction : newvirtual task body();`uvm_info(get_type_name(),"Starting sequence", UVM_HIGH)trans_status = OK;foreach(data[i]) begin`uvm_do_with(req, {trans_kind == READ; addr == local::addr + (i<<2); idle_cycles == 0;})get_response(rsp);data[i] = rsp.data;end`uvm_do_with(req, {trans_kind == IDLE;})get_response(rsp);trans_status = rsp.trans_status == ERROR ? ERROR : trans_status;`uvm_info(get_type_name(),$psprintf("Done sequence: %s",req.convert2string()), UVM_HIGH)endtask: body
endclass: lvc_apb_master_burst_read_sequence`endif // LVC_APB_MASTER_SEQ_LIB_SV

apb_test: 包括apb的env

        apb_env extends uvm_env:例化mst、slv agent,并工厂创建;

        apb_base_test extends uvm_test:例化apb_env、apb_cfg;注册、new();build()中工厂创建cfg,对cfg中控制pready次数、pslverr状态变量赋值,并set到env中,工厂创建env;

        base_test_sequence extends uvm_sequence #(lvc_apb_transfer):定义bit[31:0] mem[bit[31:0]]; 函数check_mem_data是判断给入的addr在mem中有没有数据,有的话数据是不是等于给入的data,没有的话数据是不是等于默认数据;任务wait_reset_release等待一个reset下降沿和上升沿(重置和释放);任务wait_cycles 等待多个时钟周期;函数get_rand_addr 定义32位addr保证[31:12]和[1:0]位为0,其余随机,并返回addr;

        single_transaction_sequence extends apb_base_test_sequence:例化mst中的单读 单写 先写后读的seq;定义控制发生次数的变量test_num;body()中定义32位addr变量,调用base test中任务wait_reset_release、wait_cycles 和 调用get_rand_addr返回一个addr赋值给addr做单写,并存放mem[addr]=addr中;做单读,并判断trans_status为OK后,调用check_mem_data检查mem[addr]中存放的addr数据和读回来的是否相同;和先写后读、写两次立刻读;

        single_transaction_test:例化上一个seq,raise_objection,seq.start(env.mst.sequencer)开始传输将seq挂载到mst.sqr,drop_objection;

        burst_transaction_sequence:例化burst_write_seq、burst_read_seq;定义传输次数;基本等同single_transaction_sequence;

        burst_transaction_test;

`ifndef LVC_APB_TESTS_SV
`define LVC_APB_TESTS_SVimport lvc_apb_pkg::*;class lvc_apb_env extends uvm_env;lvc_apb_master_agent mst;lvc_apb_slave_agent slv;`uvm_component_utils(lvc_apb_env)function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);mst = lvc_apb_master_agent::type_id::create("mst", this);slv = lvc_apb_slave_agent::type_id::create("slv", this);endfunction
endclassclass lvc_apb_base_test extends uvm_test;lvc_apb_env env;lvc_apb_config cfg;`uvm_component_utils(lvc_apb_base_test)function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);cfg = lvc_apb_config::type_id::create("cfg");// USER TODO// Option-1 manually set the config parameters // cfg.slave_pready_default_value = 1;// cfg.slave_pready_random = 1;// cfg.slave_pslverr_random = 1;// Option-2 randomize the config parameters// void'(cfg.randomize());uvm_config_db#(lvc_apb_config)::set(this,"env.*","cfg", cfg);env = lvc_apb_env::type_id::create("env", this);endfunction
endclassclass lvc_apb_base_test_sequence extends uvm_sequence #(lvc_apb_transfer);bit[31:0] mem[bit[31:0]];`uvm_object_utils(lvc_apb_base_test_sequence)function new(string name=""); super.new(name);endfunction : newfunction bit check_mem_data(bit[31:0] addr, bit[31:0] data);if(mem.exists(addr)) beginif(data != mem[addr]) begin`uvm_error("CMPDATA", $sformatf("addr 32'h%8x, READ DATA expected 32'h%8x != actual 32'h%8x", addr, mem[addr], data))return 0;endelse begin`uvm_info("CMPDATA", $sformatf("addr 32'h%8x, READ DATA 32'h%8x comparing success!", addr, data), UVM_LOW)return 1;endendelse beginif(data != DEFAULT_READ_VALUE) begin`uvm_error("CMPDATA", $sformatf("addr 32'h%8x, READ DATA expected 32'h%8x != actual 32'h%8x", addr, DEFAULT_READ_VALUE, data))return 0;endelse begin`uvm_info("CMPDATA", $sformatf("addr 32'h%8x, READ DATA 32'h%8x comparing success!", addr, data), UVM_LOW)return 1;endendendfunction: check_mem_datatask wait_reset_release();@(negedge lvc_apb_tb.rstn);@(posedge lvc_apb_tb.rstn);endtasktask wait_cycles(int n);repeat(n) @(posedge lvc_apb_tb.clk);endtaskfunction bit[31:0] get_rand_addr();bit[31:0] addr;void'(std::randomize(addr) with {addr[31:12] == 0; addr[1:0] == 0;addr != 0;});return addr;endfunction
endclassclass lvc_apb_single_transaction_sequence extends lvc_apb_base_test_sequence;lvc_apb_master_single_write_sequence single_write_seq;lvc_apb_master_single_read_sequence single_read_seq;lvc_apb_master_write_read_sequence write_read_seq;rand int test_num = 100;constraint cstr{soft test_num == 100;}`uvm_object_utils(lvc_apb_single_transaction_sequence)    function new(string name=""); super.new(name);endfunction : newtask body();bit[31:0] addr;this.wait_reset_release();this.wait_cycles(10);// TEST continous write transaction`uvm_info(get_type_name(), "TEST continous write transaction...", UVM_LOW)repeat(test_num) beginaddr = this.get_rand_addr();`uvm_do_with(single_write_seq, {addr == local::addr; data == local::addr;})mem[addr] = addr;end// TEST continous read transaction`uvm_info(get_type_name(), "TEST continous read transaction...", UVM_LOW)repeat(test_num) beginaddr = this.get_rand_addr();`uvm_do_with(single_read_seq, {addr == local::addr;})if(single_read_seq.trans_status == OK)void'(this.check_mem_data(addr, single_read_seq.data));end// TEST read transaction after write transaction`uvm_info(get_type_name(), "TEST read transaction after write transaction...", UVM_LOW)repeat(test_num) beginaddr = this.get_rand_addr();`uvm_do_with(single_write_seq, {addr == local::addr; data == local::addr;})mem[addr] = addr;`uvm_do_with(single_read_seq, {addr == local::addr;})if(single_read_seq.trans_status == OK)void'(this.check_mem_data(addr, single_read_seq.data));end// TEST read transaction immediately after write transaction`uvm_info(get_type_name(), "TEST read transaction immediately after write transaction", UVM_LOW)repeat(test_num) beginaddr = this.get_rand_addr();`uvm_do_with(write_read_seq, {addr == local::addr; data == local::addr;})mem[addr] = addr;if(write_read_seq.trans_status == OK)void'(this.check_mem_data(addr, write_read_seq.data));end// TODO// TEST write twice and read immediately with burst transaction`uvm_info(get_type_name(), "TEST write twice and read immediately with burst transaction...", UVM_LOW)repeat(test_num) beginaddr = this.get_rand_addr();// WRITE first time`uvm_do_with(req,  {trans_kind == WRITE; addr == local::addr; data == local::addr;idle_cycles == 0;})mem[addr] = addr;get_response(rsp);// WRITE second time`uvm_do_with(req,  {trans_kind == WRITE; addr == local::addr; data == local::addr<<2;idle_cycles == 0;})mem[addr] = addr<<2;get_response(rsp);// READ immediately after WRITE`uvm_do_with(req, {trans_kind == READ; addr == local::addr;})get_response(rsp);if(rsp.trans_status == OK)void'(this.check_mem_data(addr, rsp.data));endthis.wait_cycles(10);endtask
endclass: lvc_apb_single_transaction_sequenceclass lvc_apb_single_transaction_test extends lvc_apb_base_test;`uvm_component_utils(lvc_apb_single_transaction_test)function new(string name, uvm_component parent);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);lvc_apb_single_transaction_sequence seq = new();phase.raise_objection(this);super.run_phase(phase);seq.start(env.mst.sequencer);phase.drop_objection(this);endtask
endclass: lvc_apb_single_transaction_testclass lvc_apb_burst_transaction_sequence extends lvc_apb_base_test_sequence;lvc_apb_master_burst_write_sequence burst_write_seq;lvc_apb_master_burst_read_sequence burst_read_seq;rand int test_num = 100;constraint cstr{soft test_num == 100;}`uvm_object_utils(lvc_apb_burst_transaction_sequence)function new(string name=""); super.new(name);endfunction : newtask body();bit[31:0] addr;this.wait_reset_release();this.wait_cycles(10);// TEST continous write transactionrepeat(test_num) beginaddr = this.get_rand_addr();`uvm_do_with(burst_write_seq, {addr == local::addr;})foreach(burst_write_seq.data[i]) beginmem[addr+(i<<2)] = burst_write_seq.data[i];end`uvm_do_with(burst_read_seq, {addr == local::addr; data.size() == burst_write_seq.data.size();})foreach(burst_read_seq.data[i]) beginvoid'(this.check_mem_data(addr+(i<<2), burst_write_seq.data[i]));endendthis.wait_cycles(10);endtask
endclass: lvc_apb_burst_transaction_sequenceclass lvc_apb_burst_transaction_test extends lvc_apb_base_test;`uvm_component_utils(lvc_apb_burst_transaction_test)function new(string name, uvm_component parent);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);lvc_apb_burst_transaction_sequence seq = new();phase.raise_objection(this);super.run_phase(phase);seq.start(env.mst.sequencer);phase.drop_objection(this);endtask
endclass: lvc_apb_burst_transaction_test`endif // LVC_APB_TESTS_SV


http://www.ppmy.cn/news/230396.html

相关文章

黑苹果关机不断电解决方法

进入&#xff1a;/EFI/CLOVER/dirvers64UEFI 下 添加&#xff1a;EmuVariableUefi-64.efi 使用Kext Utility 修复权限和重建缓存重启即可

DW1820a 黑苹果开机一段时间 卡死机问题或者屏蔽针脚问题

屏蔽针脚的时候 不要用透明胶带, 不要用透明胶带 不要用透明胶带 要用电工胶带 我的屏蔽一面即可,大家可以借鉴一下 ,我只屏蔽了背面的两个针脚 . 机型是 机械革命x7tis

什么是黑苹果(Hackintosh)

什么是黑苹果&#xff1f; 非苹果电脑使用Macos系统的设备&#xff0c;简称黑苹果&#xff08;Hackintosh&#xff09; 苹果公司的Macos系统&#xff0c;一直针对的是自家电脑&#xff0c;普通的PC电脑无法直接使用苹果的系统。随着大神们对Macos系统研究&#xff0c;黑苹果技…

假如苹果公司倒闭了,会对iOS及macOS用户产生什么影响?

首先苹果公司是不会一天之内瞬间倒闭的。那么他在倒闭前会发生什么呢&#xff1f; 首先是股价大跌&#xff0c;投资者的不信任以及市场的恶化导致苹果公司开始裁员&#xff0c;部分创新项目暂停甚至撤下&#xff08;比如智能眼镜&#xff0c;智能家居&#xff0c;智能汽车&…

黑苹果 MAC Monterey 在睡眠后 bluetoothd 占用很高的cpu解决方案

问题 在安装了黑苹果后&#xff0c;在睡眠唤醒后&#xff0c;bluetoothd这个进程会占用200%的CPU&#xff0c;使cpu 的温度急剧升高&#xff0c;找了很久也没找到解决方法。下面列出我的解决方案 解决 首先使用homebrew安装sleepwatcher和blueutil brew install (sleepwatch…

黑苹果各种问题汇总

1.opencore com.apple.applefscompressiontypedataless kmod start 2.com.apple.AppleFSCompressionTypeZlib load succeeded 3.ifnet:attach: All kernel threads created for interface lo0 have been scheduled at least once. Proceeding 整了半天好像我的打开这个就可以…

苹果手机经常开低电量模式,对电池会有影响吗?

苹果手机经常开低电量模式&#xff0c;对电池会有影响吗&#xff1f;需要注意什么问题&#xff1f; 苹果手机开启低电量模式&#xff0c;对电池是没有影响的。 不过虽然对电池没有影响&#xff0c;但是对您的一些功能的使用会产生影响。 比如说&#xff1a;邮箱将不再接收邮件…

苹果曝出严重安全漏洞:黑客能接管设备 几乎涵盖了所有苹果产品

近日&#xff0c;“苹果曝出严重安全漏洞”直接登顶微博热搜榜第一。美国苹果公司发布两份安全报告&#xff0c;披露公司旗下智能手机iPhone、平板电脑iPad和iMac电脑等产品存在严重安全漏洞。 这些漏洞可能会让潜在的攻击者入侵用户设备、获得管理权限甚至完全控制设备并运行其…