• 电力电子转战数字IC20220720day53——同步通信元件


    • SV中线程同步:semaphore、event、mailbox
    • uvm中的同步是不同组件之间的线程同步问题,要求组件之间实现同步

    uvm_event与uvm_event_pool

    • event被→触发后会触发使用@等待该事件的对象,如果要再次触发,还是需要用→来触发;无法携带更多的信息;无法直接触发回调函数;无法直接获取等待他的进程数目
    • uvm_event,可以实现上面所有的无法:通过trigger()来触发,会触发使用wait_trigger()等待该事件的对象,再次触发需要先通过reset()方法重置初始状态再用trigger触发;可以通过trigger(T data=null)的可选参数将伴随触发的数据对象都写入到该触发事件中,等待该事件的对象可以通过wait_trigger_data(output T data)来获取事件触发时写入的数据对象;通过add_callback(uvm_event_callback cb, bit append=1)函数来添加回调函数;get_num_waiters()
    • 不同组件可以共享同一个uvm_event,这个共享方式是通过uvm_event_pool这一全局资源池来实现(uvm_object_string_pool #(T)的子类,可以生成和获取通过字符串来索引的uvm_event对象)
    • 环境中的任何组件都可以从资源池获取共享的对象句柄,避免组件之间相互依赖
    1. class edata extends uvm_object;
    2. int data;
    3. `uvm_object_utils(edata)
    4. ...endclass
    5. class ecb extends uvm_event_callback;
    6. `uvm_object_utils(ecb)
    7. ...//函数名一定是这两个,参数可以设置data
    8. function bit pre_trigger(uvm_event e, uvm_object data=null);
    9. `uvm_info("", $sformatf(), UVM_LOW)
    10. return 0;//这个函数需要有返回值,如果返回1则表示uvm_event不会被trigger,也不会执行下面的post
    11. endfunction
    12. function void post_trigger(uvm_event e, uvm_object data=null);
    13. `uvm_info()
    14. endfunction
    15. endclass
    16. class comp1 extends uvm_component;
    17. uvm_event e1;
    18. `uvm_component_utils()
    19. ...
    20. function void build_phase(...);
    21. super....
    22. e1=uvm_event_pool::get_global("e1");//借助全局的event_pool例化event1
    23. //如果没有呢?会帮你创建一个e1的句柄
    24. endfunction
    25. task run_phase(...);
    26. edata d=new();
    27. ecb cb=new();
    28. d.data=100;
    29. #10ns;
    30. e1.add_callback(cb);//将例化了的cb和e1关联起来,在e1被trigger时也会调用回调函数
    31. e1.trigger(d);//trigger时带上数据d
    32. `uvm_info()
    33. endtask
    34. endclass
    35. class comp2 extends uvm_component;
    36. uvm_event e1;
    37. `uvm_component_utils()
    38. ...
    39. function void build(...);
    40. super.b.....
    41. e1=uvm_event_pool::get_global("e1");//也拿一个e1
    42. endfunction
    43. task run_phase(...);
    44. uvm_object tmp;
    45. edata d;
    46. `uvm_info()
    47. e1.wait_trigger_data(tmp);//等待e1被触发,tmp是一个object类型
    48. //既等到了trigger的event,也等到了event带来的数据
    49. void'($cast(d, tmp));//父类转子类
    50. `uvm_info()
    51. endtask
    52. class env1 extends uvm_env;
    53. comp1 c1;
    54. comp2 c2;
    55. `uvm_component_utils()
    56. ...endclass
    • 无论多少个组件,只要寻求同一个名称的uvm_event,就可以共享这个uvm_event对象(通过pool::get_global)
    • 需要传递数据就定义扩展于uvm_object的数据子类,通过uvm_event::trigger(T data=null)来传递数据对象
    • 等待的组件通过uvm_event::wait_trigger_data(output T data)获取该对象
    • 如果无法确定在等待事件之前,uvm_event是否已经被trigger,可以通过方法wait_ptrigger()和wait_ptrigger_data()来完成等待。这样即使event被trigger,等待方法仍可继续执行
    • 使用场景:偶然触发的数据传输,且需要立即响应
    • 使用场景:uvm_object和uvm_component对象之间要发生同步
    • 使用场景:sequence与sequence之间,sequence与driver之间进行同步
    • 注意:TLM传输必须是在component之间完成,不能在component和object之间

    uvm_barrier与uvm_barrier_pool

    • 作用:对多个组件进行同步协调
    • 定义了新的类uvm_barrier_pool来全局管理这些uvm_barrier对象(同event_pool,也是基于通用参数类uvm_object_string_pool定义的)

    • 定义
    1. typedef uvm_object_string_pool #(uvm_barrier) uvm_barrier_pool;
    2. typedef uvm_object_string_pool #(uvm_event#(uvm_object)) uvm_event_pool;
    • uvm_barrier可以设置等待阈值threshold,当有不少于threshold的进程在等待该对象时才会触发该事件,同时激活所有正在等待的进程
    1. class comp1 extends uvm_component;
    2. uvm_barrier b1;
    3. `uvm_component_utils(comp1)
    4. ...
    5. function void build_phase(uvm_phase phase);
    6. super....
    7. b1=uvm_barrier_pool::get_global("b1");
    8. endfunction
    9. task run_phase(uvm_phase phase);
    10. #10ns;
    11. `uvm_info()
    12. b1.wait_for();//站在起跑线上等待c2
    13. `uvm_info()
    14. endtask
    15. endclass
    16. class comp2 extends uvm_component;
    17. uvm_barrier b2;
    18. `uvm_component_utils(comp2)
    19. ...
    20. function void build_phase(uvm_phase phase);
    21. super....
    22. b1=uvm_barrier_pool::get_global("b1");
    23. endfunction
    24. task run_phase(uvm_phase phase);
    25. #20ns;
    26. `uvm_info()
    27. b1.wait_for();
    28. `uvm_info()
    29. endtask
    30. endclass
    31. class env1 extends uvm_env;
    32. comp1 c1;
    33. comp2 c2;
    34. uvm_barrier b1;
    35. `uvm_component_utils(env1)
    36. ...
    37. function void build_phase(uvm_phase phase);
    38. super.build_phase(phase);
    39. c1=comp1::type_id::create("c1", this);
    40. c2=comp2::type_id::create("c2", this);
    41. b1=uvm_barrier_pool::get_global("b1");
    42. endfunction
    43. task tun_phase(uvm_phase phase);
    44. b1.set_threshold(3);//要等到3个
    45. `uvm_info("BSYNC", $sformatf("", b1.get_threshold(), $time), UVM_LOW)
    46. #50ns;
    47. b1.set_threshold(2);//满足2个了,枪响,c1和c2继续执行wait_for后面的语句
    48. `uvm_info()
    49. endtask
    50. endclass

    uvm_event_callback

    • 作用:延展之前的方法;也是一种同步方式
    • uvm_object提供的callback方法,默认情况do_是空的
      • copy() do_copy()
      • print() do_print()
      • compare() do_compare()
      • pack() do_pack()
      • unpack() do_unpack()
      • record() do_record()
    • 如果执行了uvm_object()::copy(),那么在函数执行末尾会自动执行uvm_object::do_copy()
    • uvm通过uvm_callback_iter类和uvm_callbacks #(T, CB)类实现函数毁掉的顺序和继承性
    1. class edata extends uvm_object;
    2. int data;
    3. `uvm_object_utils(edata)
    4. ...endclass
    5. class cb1 extends uvm_callback;
    6. `uvm_object_utils(cb1)
    7. ...//回调类中可以定义任何名称的方法
    8. virtual function void do_trans(edata d);//do_trans不是预定义好的
    9. d.data=200;
    10. `uvm_info(executed)
    11. endfunction
    12. endclass
    13. class cb2 extends cb1;
    14. `uvm_object_utils(cb2)
    15. ...
    16. function void do_trans(edata d);
    17. d.data=300;
    18. `uvm_info()
    19. endfunction
    20. endclass
    21. class comp1 extends uvm_component;
    22. `uvm_component_utils()
    23. `uvm_register_cb(comp1, cb1)//注册callback,将cb1和comp1关联起来
    24. ...
    25. task run_phase(uvm_phase phase);
    26. edata d=new();
    27. d.data=100;
    28. `uvm_info(proceeding)
    29. `uvm_do_callbacks(comp1, cb1, do_trans(d))//绑定与插入callback,域->类型->方法
    30. class env1 extends uvm_env;
    31. comp1 c1;
    32. cb1 m_cb1;
    33. cb2 m_cb2;
    34. `uvm_component_utils(env1)
    35. function new(string name, uvm_component parent);
    36. super.new(name, parent);
    37. m_cb1=new("m_cb1");
    38. m_cb2=new("m_cb2");
    39. endfunction
    40. function void build_phase(uvm_phase phase);
    41. super.build_phase(phase);
    42. c1=comp1::type_id::create("c1", this);
    43. uvm_callbacks #(comp1)::add(c1, m_cb1);//添加callback进来
    44. cb2同上
    45. endfunction
    46. endclass
    • uvm_callback建立了回调函数执行的层次性,通过宏`uvm_do_callbacks(T, CB, METHOD)循环执行与该对象结对的uvm_callback类的方法
    • `uvm_do_callbacks_exit_on(T, CB,METHOD, VAL)可以进一步控制执行回调函数的层次,回调函数会保持执行直到返回值与VAL相同才会返回
  • 相关阅读:
    requests库中解决字典值中列表在URL编码时的问题
    1668、最大重复子字符串(暴力+KMP+strstr)
    gitignore文件不生效问题
    git学习笔记
    如何卸载干净 IDEA(图文讲解)windows和Mac教程
    关于element-ui的样式覆盖问题
    域名一定需要备案吗?什么情况下不用备案?
    【cs231n】Lecture 2 : Image Classification pipeline 图像分类管道
    MySQL 常见存储引擎详解(一)
    01.bpmn-js 样例项目解析-启动
  • 原文地址:https://blog.csdn.net/weixin_39668316/article/details/125893479