• 电力电子转战数字IC20220817day62——uvm入门实验4


    目录

    实验目标 

    存在问题 

     实验任务

    1.1移除driver中的mailbox句柄和do_drive()中用mailbox句柄通信的方式,用driver自带的seq_item_port通信;定义对应的uvm_sequencer

    1.2将generator中发送trans的任务改为底层sequence。将mcdf_base_test中的idle_reg()和write_reg()和read_reg()提取改为seq

    1.3在agent中声明、例化sequencer,并TLM连接到driver

    1.4去掉generator在mcdf_base_test中的声明+例化+连接到driver

    1.5去掉1.2中已经提取为seq的三个task

    1.6实现MCDF顶层的virtual sequencer

    1.7连接virtual sequencer和底层sequencer的句柄

    1.8将所有发送序列的顺序和组织等内容移植到mcdf_base_virtual_sequence,需要将mcdf_base_test::run_phase()发送序列的功能移植到mcdf_base_virtual_sequence;mcdf_base_test::run_phase()只需要挂载对应的顶层sequence

    1.9将原本test中产生和发送trans的任务提取到mcdf_data_consistence_basic_virtual_sequence中


    实验目标 

    存在问题 

    主要是关于sequence和sequencer的,见之前的笔记,没有太多改变。

     实验任务

    1.1移除driver中的mailbox句柄和do_drive()中用mailbox句柄通信的方式,用driver自带的seq_item_port通信;定义对应的uvm_sequencer

    首先是去掉mailbox的定义

    1. class chnl_driver extends uvm_driver #(chnl_trans);
    2. local virtual chnl_intf intf;
    3. // mailbox #(chnl_trans) req_mb;
    4. // mailbox #(chnl_trans) rsp_mb;

    在do_drive()中将原来用mailbox通信的方式改为PORT通信。通过driver的seq_item_port端口调用get_next_item(req)获取req,由sequence的函数set_sequence_id设置id,所用id为req这个item调用get_sequence_id得到的;最后返回rsp。

    1. task do_drive();
    2. chnl_trans req, rsp;
    3. @(posedge intf.rstn);
    4. forever begin
    5. // this.req_mb.get(req);
    6. this.chnl_write(req);
    7. void'($cast(rsp, req.clone()));
    8. rsp.rsp = 1;
    9. // this.rsp_mb.put(rsp);
    10. end
    11. endtask
    12. task do_drive();
    13. chnl_trans req, rsp;
    14. @(posedge intf.rstn);
    15. forever begin
    16. //TODO-1.1 Use seq_item_port to get request item
    17. seq_item_port.get_next_item(req);
    18. this.chnl_write(req);
    19. void'($cast(rsp, req.clone()));
    20. rsp.rsp = 1;
    21. //TODO-1.1 Use seq_item_port to put response item
    22. rsp.set_sequence_id(req.get_sequence_id());
    23. seq_item_port.item_done(rsp);
    24. end
    25. endtask

    定义sequencer,只需要注册和new函数即可,注意是参数类的要加参数#()

    1. class chnl_sequencer extends uvm_sequencer #(chnl_trans);
    2. `uvm_component_utils(chnl_sequencer)
    3. function new (string name = "chnl_sequencer", uvm_component parent);
    4. super.new(name, parent);
    5. endfunction
    6. endclass: chnl_sequencer

    在fmt_pkg和reg_pkg中的操作完全相同。

    1.2将generator中发送trans的任务改为底层sequence。将mcdf_base_test中的idle_reg()和write_reg()和read_reg()提取改为seq

    改造generator:不需要mailbox;由于变成sequence,start任务变成body()任务;将原来assert with做随机化约束变成`uvm_do_with;将mailbox通信改为seq通信;注意也是个参数类#()

    1. class chnl_data_sequence extends uvm_sequence #(chnl_trans);
    2. rand int pkt_id = 0;
    3. rand int ch_id = -1;
    4. rand int data_nidles = -1;
    5. rand int pkt_nidles = -1;
    6. rand int data_size = -1;
    7. rand int ntrans = 10;
    8. `uvm_object_utils_begin(chnl_data_sequence)
    9. `uvm_field_int(pkt_id, UVM_ALL_ON)
    10. `uvm_field_int(ch_id, UVM_ALL_ON)
    11. `uvm_field_int(data_nidles, UVM_ALL_ON)
    12. `uvm_field_int(pkt_nidles, UVM_ALL_ON)
    13. `uvm_field_int(data_size, UVM_ALL_ON)
    14. `uvm_field_int(ntrans, UVM_ALL_ON)
    15. `uvm_object_utils_end
    16. `uvm_declare_p_sequencer(chnl_sequencer)
    17. function new (string name = "chnl_data_sequence");
    18. super.new(name);
    19. endfunction
    20. task body();
    21. repeat(ntrans) send_trans();
    22. endtask
    23. task send_trans();
    24. chnl_trans req, rsp;
    25. `uvm_do_with(req, {local::ch_id >= 0 -> ch_id == local::ch_id;
    26. local::pkt_id >= 0 -> pkt_id == local::pkt_id;
    27. local::data_nidles >= 0 -> data_nidles == local::data_nidles;
    28. local::pkt_nidles >= 0 -> pkt_nidles == local::pkt_nidles;
    29. local::data_size >0 -> data.size() == local::data_size;
    30. })
    31. this.pkt_id++;
    32. `uvm_info(get_type_name(), req.sprint(), UVM_HIGH)
    33. get_response(rsp);
    34. `uvm_info(get_type_name(), rsp.sprint(), UVM_HIGH)
    35. assert(rsp.rsp)
    36. else $error("[RSPERR] %0t error response received!", $time);
    37. endtask
    38. function void post_randomize();
    39. string s;
    40. s = {s, "AFTER RANDOMIZATION \n"};
    41. s = {s, "=======================================\n"};
    42. s = {s, "chnl_data_sequence object content is as below: \n"};
    43. s = {s, super.sprint()};
    44. s = {s, "=======================================\n"};
    45. `uvm_info(get_type_name(), s, UVM_HIGH)
    46. endfunction
    47. endclass: chnl_data_sequence

    在fmt_pkg和reg_pkg中的操作完全相同。

    1. //原来在mcdf_base_test中的三个虚任务
    2. virtual task idle_reg();
    3. void'(reg_gen.randomize() with {cmd == `IDLE; addr == 0; data == 0;});
    4. reg_gen.start();
    5. endtask
    6. virtual task write_reg(bit[7:0] addr, bit[31:0] data);
    7. void'(reg_gen.randomize() with {cmd == `WRITE; addr == local::addr; data == local::data;});
    8. reg_gen.start();
    9. endtask
    10. virtual task read_reg(bit[7:0] addr, output bit[31:0] data);
    11. void'(reg_gen.randomize() with {cmd == `READ; addr == local::addr;});
    12. reg_gen.start();
    13. data = reg_gen.data;
    14. endtask
    15. //被替换成reg_pkg中的三个sequence,分别做约束,注册恶,new函数
    16. class idle_reg_sequence extends reg_base_sequence;
    17. constraint cstr{
    18. addr == 0;
    19. cmd == `IDLE;
    20. data == 0;
    21. }
    22. `uvm_object_utils(idle_reg_sequence)
    23. function new (string name = "idle_reg_sequence");
    24. super.new(name);
    25. endfunction
    26. endclass: idle_reg_sequence
    27. class write_reg_sequence extends reg_base_sequence;
    28. constraint cstr{
    29. cmd == `WRITE;
    30. }
    31. `uvm_object_utils(write_reg_sequence)
    32. function new (string name = "write_reg_sequence");
    33. super.new(name);
    34. endfunction
    35. endclass: write_reg_sequence
    36. class read_reg_sequence extends reg_base_sequence;
    37. constraint cstr{
    38. cmd == `READ;
    39. }
    40. `uvm_object_utils(read_reg_sequence)
    41. function new (string name = "read_reg_sequence");
    42. super.new(name);
    43. endfunction
    44. endclass: read_reg_sequence

    1.3在agent中声明、例化sequencer,并TLM连接到driver

    1. class chnl_agent extends uvm_agent;
    2. chnl_driver driver;
    3. chnl_monitor monitor;
    4. //声明sequencer
    5. chnl_sequencer sequencer;
    6. local virtual chnl_intf vif;
    7. `uvm_component_utils(chnl_agent)
    8. function new(string name = "chnl_agent", uvm_component parent);
    9. super.new(name, parent);
    10. endfunction
    11. function void build_phase(uvm_phase phase);
    12. super.build_phase(phase);
    13. driver = chnl_driver::type_id::create("driver", this);
    14. monitor = chnl_monitor::type_id::create("monitor", this);
    15. //例化sequencer
    16. sequencer = chnl_sequencer::type_id::create("sequencer", this);
    17. endfunction
    18. function void connect_phase(uvm_phase phase);
    19. super.connect_phase(phase);
    20. //连接driver和sequencer
    21. driver.seq_item_port.connect(sequencer.seq_item_export);
    22. endfunction
    23. function void set_interface(virtual chnl_intf vif);
    24. this.vif = vif;
    25. driver.set_interface(vif);
    26. monitor.set_interface(vif);
    27. endfunction
    28. endclass: chnl_agent

    在fmt_pkg和reg_pkg中的操作完全相同。

    1.4去掉generator在mcdf_base_test中的声明+例化+连接到driver

    1.5去掉1.2中已经提取为seq的三个task

    1.6实现MCDF顶层的virtual sequencer

    virtual sequencer包含所有底层sequencer的句柄

    1. class mcdf_virtual_sequencer extends uvm_sequencer;
    2. reg_sequencer reg_sqr;
    3. fmt_sequencer fmt_sqr;
    4. chnl_sequencer chnl_sqrs[3];
    5. `uvm_component_utils(mcdf_virtual_sequencer)
    6. function new (string name = "mcdf_virtual_sequencer", uvm_component parent);
    7. super.new(name, parent);
    8. endfunction
    9. endclass

    1.7连接virtual sequencer和底层sequencer的句柄

    1. class mcdf_env extends uvm_env;
    2. chnl_agent chnl_agts[3];
    3. reg_agent reg_agt;
    4. fmt_agent fmt_agt;
    5. mcdf_checker chker;
    6. mcdf_coverage cvrg;
    7. //声明
    8. mcdf_virtual_sequencer virt_sqr;
    9. `uvm_component_utils(mcdf_env)
    10. function new (string name = "mcdf_env", uvm_component parent);
    11. super.new(name, parent);
    12. endfunction
    13. function void build_phase(uvm_phase phase);
    14. super.build_phase(phase);
    15. this.chker = mcdf_checker::type_id::create("chker", this);
    16. foreach(chnl_agts[i]) begin
    17. this.chnl_agts[i] = chnl_agent::type_id::create($sformatf("chnl_agts[%0d]",i), this);
    18. end
    19. this.reg_agt = reg_agent::type_id::create("reg_agt", this);
    20. this.fmt_agt = fmt_agent::type_id::create("fmt_agt", this);
    21. this.cvrg = mcdf_coverage::type_id::create("cvrg", this);
    22. //例化
    23. virt_sqr = mcdf_virtual_sequencer::type_id::create("virt_sqr", this);
    24. endfunction
    25. function void connect_phase(uvm_phase phase);
    26. super.connect_phase(phase);
    27. chnl_agts[0].monitor.mon_bp_port.connect(chker.chnl0_bp_imp);
    28. chnl_agts[1].monitor.mon_bp_port.connect(chker.chnl1_bp_imp);
    29. chnl_agts[2].monitor.mon_bp_port.connect(chker.chnl2_bp_imp);
    30. reg_agt.monitor.mon_bp_port.connect(chker.reg_bp_imp);
    31. fmt_agt.monitor.mon_bp_port.connect(chker.fmt_bp_imp);
    32. //和底层的sequencer连接起来
    33. virt_sqr.reg_sqr = reg_agt.sequencer;
    34. virt_sqr.fmt_sqr = fmt_agt.sequencer;
    35. foreach(virt_sqr.chnl_sqrs[i]) virt_sqr.chnl_sqrs[i] = chnl_agts[i].sequencer;
    36. endfunction
    37. endclass: mcdf_env

    1.8将所有发送序列的顺序和组织等内容移植到mcdf_base_virtual_sequence,需要将mcdf_base_test::run_phase()发送序列的功能移植到mcdf_base_virtual_sequence;mcdf_base_test::run_phase()只需要挂载对应的顶层sequence

    就是对应virtual sequencer的顶层virtual sequence。

    1. class mcdf_base_virtual_sequence extends uvm_sequence;
    2. //对应virtual sequencer的顶层virtual sequence
    3. idle_reg_sequence idle_reg_seq;
    4. write_reg_sequence write_reg_seq;
    5. read_reg_sequence read_reg_seq;
    6. chnl_data_sequence chnl_data_seq;
    7. fmt_config_sequence fmt_config_seq;
    8. `uvm_object_utils(mcdf_base_virtual_sequence)
    9. `uvm_declare_p_sequencer(mcdf_virtual_sequencer)
    10. function new (string name = "mcdf_base_virtual_sequence");
    11. super.new(name);
    12. endfunction
    13. virtual task body();
    14. `uvm_info(get_type_name(), "=====================STARTED=====================", UVM_LOW)
    15. this.do_reg();
    16. this.do_formatter();
    17. this.do_data();
    18. `uvm_info(get_type_name(), "=====================FINISHED=====================", UVM_LOW)
    19. endtask
    20. // do register configuration
    21. virtual task do_reg();
    22. endtask
    23. // do external formatter down stream slave configuration
    24. virtual task do_formatter();
    25. endtask
    26. // do data transition from 3 channel slaves
    27. virtual task do_data();
    28. endtask
    29. virtual function bit diff_value(int val1, int val2, string id = "value_compare");
    30. if(val1 != val2) begin
    31. `uvm_error("[CMPERR]", $sformatf("ERROR! %s val1 %8x != val2 %8x", id, val1, val2))
    32. return 0;
    33. end
    34. else begin
    35. `uvm_info("[CMPSUC]", $sformatf("SUCCESS! %s val1 %8x == val2 %8x", id, val1, val2), UVM_LOW)
    36. return 1;
    37. end
    38. endfunction
    39. endclass

    而在mcdf_base_test::run_phase()中只需要运行对应的虚方法

    1. task run_phase(uvm_phase phase);
    2. phase.raise_objection(this);
    3. this.run_top_virtual_sequence();
    4. phase.drop_objection(this);
    5. endtask
    6. virtual task run_top_virtual_sequence();
    7. endtask

    在不同的test中用继承的字方法来自定义所需要的的seq

    1. task run_top_virtual_sequence();
    2. mcdf_data_consistence_basic_virtual_sequence top_seq = new();
    3. top_seq.start(env.virt_sqr);
    4. endtask
    5. task run_top_virtual_sequence();
    6. mcdf_full_random_virtual_sequence top_seq = new();
    7. top_seq.start(env.virt_sqr);
    8. endtask

    1.9将原本test中产生和发送trans的任务提取到mcdf_data_consistence_basic_virtual_sequence中

    1. class mcdf_data_consistence_basic_virtual_sequence extends mcdf_base_virtual_sequence;
    2. `uvm_object_utils(mcdf_data_consistence_basic_virtual_sequence)
    3. function new (string name = "mcdf_data_consistence_basic_virtual_sequence");
    4. super.new(name);
    5. endfunction
    6. task do_reg();
    7. bit[31:0] wr_val, rd_val;
    8. // slv0 with len=8, prio=0, en=1
    9. wr_val = (1<<3)+(0<<1)+1;
    10. `uvm_do_on_with(write_reg_seq, p_sequencer.reg_sqr, {addr == `SLV0_RW_ADDR; data == wr_val;})
    11. `uvm_do_on_with(read_reg_seq, p_sequencer.reg_sqr, {addr == `SLV0_RW_ADDR;})
    12. rd_val = read_reg_seq.data;
    13. void'(this.diff_value(wr_val, rd_val, "SLV0_WR_REG"));
    14. // slv1 with len=16, prio=1, en=1
    15. wr_val = (2<<3)+(1<<1)+1;
    16. `uvm_do_on_with(write_reg_seq, p_sequencer.reg_sqr, {addr == `SLV1_RW_ADDR; data == wr_val;})
    17. `uvm_do_on_with(read_reg_seq, p_sequencer.reg_sqr, {addr == `SLV1_RW_ADDR;})
    18. rd_val = read_reg_seq.data;
    19. void'(this.diff_value(wr_val, rd_val, "SLV1_WR_REG"));
    20. // slv2 with len=32, prio=2, en=1
    21. wr_val = (3<<3)+(2<<1)+1;
    22. `uvm_do_on_with(write_reg_seq, p_sequencer.reg_sqr, {addr == `SLV2_RW_ADDR; data == wr_val;})
    23. `uvm_do_on_with(read_reg_seq, p_sequencer.reg_sqr, {addr == `SLV2_RW_ADDR;})
    24. rd_val = read_reg_seq.data;
    25. void'(this.diff_value(wr_val, rd_val, "SLV2_WR_REG"));
    26. // send IDLE command
    27. `uvm_do_on(idle_reg_seq, p_sequencer.reg_sqr)
    28. endtask
    29. task do_formatter();
    30. `uvm_do_on_with(fmt_config_seq, p_sequencer.fmt_sqr, {fifo == LONG_FIFO; bandwidth == HIGH_WIDTH;})
    31. endtask
    32. task do_data();
    33. fork
    34. `uvm_do_on_with(chnl_data_seq, p_sequencer.chnl_sqrs[0], {ntrans==100; ch_id==0; data_nidles==0; pkt_nidles==1; data_size==8; })
    35. `uvm_do_on_with(chnl_data_seq, p_sequencer.chnl_sqrs[1], {ntrans==100; ch_id==1; data_nidles==1; pkt_nidles==4; data_size==16;})
    36. `uvm_do_on_with(chnl_data_seq, p_sequencer.chnl_sqrs[2], {ntrans==100; ch_id==2; data_nidles==2; pkt_nidles==8; data_size==32;})
    37. join
    38. #10us; // wait until all data haven been transfered through MCDF
    39. endtask
    40. endclass: mcdf_data_consistence_basic_virtual_sequence

    原本在test中的处理trans的三个任务早已在1.2中被提取为sequence(idle_reg_seq,write_reg_seq,read_reg_seq )

    现在的test只剩下注册,new函数,运行顶层virtual seq的任务了

    1. class mcdf_data_consistence_basic_test extends mcdf_base_test;
    2. `uvm_component_utils(mcdf_data_consistence_basic_test)
    3. function new(string name = "mcdf_data_consistence_basic_test", uvm_component parent);
    4. super.new(name, parent);
    5. endfunction
    6. task run_top_virtual_sequence();
    7. mcdf_data_consistence_basic_virtual_sequence top_seq = new();
    8. top_seq.start(env.virt_sqr);
    9. endtask
    10. endclass: mcdf_data_consistence_basic_test

  • 相关阅读:
    2023 收入最高的十大编程语言
    Git分布式版本控制工具
    含文档+PPT+源码等]精品微信小程序校园第二课堂+后台管理系统|前后分离VUE[包运行成功]微信小程序毕业设计项目源码计算机毕设
    java源码系列:HashMap底层存储原理详解——5、技术本质-原理过程-算法-取模会带来一个什么问题?什么是哈希冲突?为什么要用链表?
    面试突击44:volatile 有什么用?
    提升VR全景摄影画质的8个因素
    DocTemplateTool - 可根据模板生成word或pdf文件的工具
    FRP内网穿透(待续)
    计算机毕业设计Java环巢湖区域旅游网站(源码+系统+mysql数据库+lw文档)
    新风机小助手-风压变速器
  • 原文地址:https://blog.csdn.net/weixin_39668316/article/details/126393986