- TLM的analysis端口与FIFO
1 analysis端口
除了port,export,imp之外,TLM还提出了另一种端口,analysis类型的端口,analysis类型的端口也会区分port,export,imp。Analysis端口与所描述的端口的差异,主要体现在两个方面:
- 一个analysis_port/analysis_export可以连接多个analysis_imp,实现一对多的连接,并且动作发起者通过广播的方式,将数据写到与之相连的全部imp上。
- analysis端口的操作不区分阻塞和非阻塞,因为是广播操作,因此只存在非阻塞的场景。
- analysis端口的广播操作通过write函数实现,且没有其他多余的操作函数(put,try_put,can_put等),因此,需要在被动接受者的主体内部实现write函数。
analysis端口的互联如图4.1.1所示。
图4.1.1 analysis端口之间的连接关系
其他特性,与常规的port,export,imp类似,一个uvm_analysis_port与uvm_analysis_export连接会报错,终点必须是uvm_analysis_imp,uvm_analysis_port,uvm_analysis_export,uvm_analysis_imp都是参数化类,且参数与常规的port,export,imp一致。
写段代码感受下:
组件A:
1. class a extend uvm_component;
2. `uvm_component_utils(a)
3. uvm_analysis_port# (my_tr) a_ap;
4. ......
5. extern function void build_phase(uvm_phase phase);
6. ......
7. endclass
8.
9. function void a::build_phase(uvm_phase phase);
10. super.build_phase(phase);
11. a_ap = new("a_ap", this);
12. ......
13. endfunction:build_phase
组件B:
1. class b extend uvm_component;
2. `uvm_component_utils(b)
3. uvm_analysis_export# (my_tr) b_aep;
4. uvm_analysis_imp#(my_tr, b) b_aimp;
5. ......
6. extern function void build_phase(uvm_phase phase);
7. extern function void connect_phase(uvm_phase phase);
8. extern function void write(my_tr tr);
9. ......
10. endclass
11.
12. function void b::build_phase(uvm_phase phase);
13. super.build_phase(phase);
14. b_aep = new("b_aep", this);
15. b_aimp = new("b_aimp", this);
16. ......
17. endfunction:build_phase
18.
19. function void b::connect_phase(uvm_phase phase);
20. super.connect_phase(uvm_phase phase);
21. this.b_aep.connect(this.b_aimp);
22. ......
23. endfunction:connect_phase
24.
25. function void b::write(my_tr tr);
26. //do something on tr
27. endfunction:write
组件B因为是动作的被动接受者,因此其中有write函数,组件C与组件B类似,不在赘述。
TOP代码,体现连接关系:
1. class TOP extend uvm_component;
2. `uvm_component_utils(TOP)
3. a my_a;
4. b my_b;
5. c my_c;
6. ......
7. extern function void build_phase(uvm_phase phase);
8. extern function void connect_phase(uvm_phase phase);
9. ......
10. endclass
11.
12. function void TOP::build_phase(uvm_phase phase);
13. super.build_phase(phase);
14. my_a = a::type_id::create("my_a", this);
15. my_b = b::type_id::create("my_b", this);
16. my_c = c::type_id::create("my_c", this);
17. ......
18. endfunction:build_phase
19.
20. function void b::connect_phase(uvm_phase phase);
21. super.connect_phase(uvm_phase phase);
22. this.my_a.a_ap.connect(this.my_b.b_aep);
23. this.my_a.a_ap.connect(this.my_c.c_aep);
24. ......
25. endfunction:connect_phase
与常规的port,export类似,analysis类型的端口同样会遇到需要跨层次连接的情况,此类场景与常规port,export的连接关系相同,以agent组件为例,此处给出总结:
- 可以通过在agent组件中声明且实例化analysis port,在connect phase中由内向外连接到agent的analysis port(analysis export是由外向内连接)
- 可以通过在agent组件中声明analysis port或者export,不进行实例化,在connect phase中将内层次的port或者export的直接赋值给agent组件的analysis port或者export。
- 在agent中不声明也不例化,在TOP层的connect phase中,通过跨层次连接,直接将动作发起者的analysis port连接至被动接受者的analysis export或者analysis imp
2 基于FIFO的通信
整个TLM机制下,底层逻辑离不开动作发起者和被动接受者这个底层的模型基础,但实际上,在验证环境中,任何一个组件,都有可能成为动作的发起者,都有可能主动发起命令,且只有掌握主动权,才能更灵活的控制数据的流通,因此TLM机制下,实际用的最多的组件,也就是基于FIFO的数据通信。
2.1 FIFO上的端口类型
想象一下,如果两个通信的组件都是动作发起者,也就是说在发送组件需要发送数据的时候发送数据,在接受组件想要接受数据的时候接受,且还可以提供数据的暂存服务,此时FIFO可以很好的实现这个功能,FIFO可以作为整个通信过程的被动接受者而存在,如图4.2.1所示。
图4.2.1 基于FIFO的通信
FIFO上存在的端口如表4.2.1所示:
表4.2.1 FIFO上的端口
端口名 |
说明 |
属性 |
blocking_put_export |
阻塞put操作 |
IMP |
nonblocking_put_export |
非阻塞put操作 |
IMP |
put_export |
阻塞/非阻塞put操作 |
IMP |
blocking_get_export |
阻塞get操作 |
IMP |
nonblocking_get_export |
非阻塞get操作 |
IMP |
get_export |
阻塞/非阻塞get操作 |
IMP |
blocking_peek_export |
阻塞peek操作 |
IMP |
nonblocking_peek_export |
非阻塞peek操作 |
IMP |
peek_export |
阻塞/非阻塞peek操作 |
IMP |
blocking_get_peek_export |
阻塞get/peek操作 |
IMP |
nonblocking_get_peek _export |
非阻塞get/peek操作 |
IMP |
get_peek_export |
阻塞/非阻塞get/peek操作 |
IMP |
analysis_export |
analysis型 |
analysis imp |
put_ap |
analysis型 |
analysis port |
get_ap |
analysis型 |
analysis port |
在UVM TLM通信中,FIFO一共由两种类型,一是uvm_tlm_analysis_fifo #(my_transaction);另一个是uvm_tlm_fifo#(my_transaction)。两者的区别是,带analysis的fifo比不带analysis的fifo多了一个analysis_export。
看了表4.2.1,会产生一个问题,就是FIFO作为被动接受者,其上面的端口类型应该是imp才对,其实,TLM机制为了掩饰掉imp类型的端口,让用户对其不可见,在FIFO的端口声明中增加了export字样,实际上FIFO上的这些export的类型其实是IMP类型,正如表4.2.1属性列所示,读者也可以查阅FIFO的UVM源码可以获得答案。
此处说明peek操作和get操作的差异,peek操作,FIFO在完成一次数据的发送时,会在本地保留一份,而get操作则不会保留。
如图4.2.2所示FIFO上的端口:
图4.2.2 FIFO上的端口
2.2 FIFO上的操作及FIFO自身函数、FIFO深度
FIFO作为动作的被动接受者,其上面理应会存在相应类型的操作函数,实际上,当一个port或者export与FIFO相连时,会调用FIFO上的操作函数,以put操作为例,当一个uvm_blocking_put_port/export与FIFO上的blocking_put_export相连时,put操作会调用FIFO上的put函数;当一个uvm_blocking_get_port/export与FIFO上的blocking_get_export相连时,get操作会调用FIFO上的get函数。put操作会将发来的数据包存在FIFO缓存中,FIFO的缓存是通过system verilog 的mailbox实现的。get操作会将FIFO的缓存包发走。此外,FIFO上还具备try_put,can_put,try_get,can_get等等一系列操作,此处不再赘述。
UVM TLM FIFO对操作做了很好的封装,因此用户不需要再纠结是否需要在组件中自己写操作函数,因此极大程度上提高了代码开发效率。
FIFO的内置函数:
- used函数返回FIFO中存在的数据包个数
- is_empty函数用于判断FIFO是否为空
- is_full函数用于判断FIFO是否为满
- flush函数用于清空FIFO
FIFO的大小,对于uvm_tlm_fifo来讲,存在大小限制,在FIFO的new函数中可以体现:
- function new(string name, uvm_component parent=null, int size=1);
可以看到,FIFO new函数的第三个参数,实际上是FIFO的大小,默认大小为1,当size值设为0时,FIFO深度定义为无限大。而对于uvm_tlm_analysis_fifo而言,其大小默认只能是无限大,也就不存在new函数中的第三个参数。
2.3 基于FIFO的实训
在实际项目中,组件间的通讯用的最多的还是FIFO,使用FIFO可以让用户不再纠结操作函数的开发,以及组件是动作发起者还是被动接受者等角色而引入开发的难度,甚至可以忽略IMP类型的端口,直接在组件上开发port或者export,在env或者高层组件中实例化FIFO,并连接FIFO上的对应端口,即可完成组件之间的通信。且FIFO还支持循环多例化和多连接,减少了一个组件包含多个imp,还要使用`uvm_analysis_imp_decl(_xxx)来指明到底是哪个组件对应的imp,极大化简了代码,增强了可读性。
以一个具体的通讯实例为主,开发代码,环境框图如图4.2.3.1所示:
图4.2.3.1 代码实训框图
RM代码:
1. class my_mdl extend uvm_component;
2. .......
3. uvm_blocking_put_port #(my_tr) mdl_port;
4. `uvm_component_utils(my_mdl)
5.
6. extend function new(string name = "my_mdl", uvm_component parent);
7. extend virtual function void build_phase(uvm_phase phase);
8. extend virtual function void connect_phase(uvm_phase phase);
9. ......
10. extend virtual task main_phase(uvm_phase phase);
11. ......
12. endclass
13.
14. function my_mdl::new(string name="my_mdl", uvm_component parent);
15. super.new(name);
16. endfunction:new
17.
18. function void my_mdl::build_phase(uvm_phase phase);
19. super.build_phase(phase);
20. ......
21. mdl_port = new("mdl_port", this);
22. endfunction:build_phase
23.
24. ......
RM中例化port。
Scoreboard代码:
1. class my_scb extend uvm_scoreboard;
2. .......
3. uvm_blocking_get_port #(my_tr) scb_port;
4. `uvm_component_utils(my_scb)
5.
6. extend function new(string name = "my_scb", uvm_component parent);
7. extend virtual function void build_phase(uvm_phase phase);
8. extend virtual function void connect_phase(uvm_phase phase);
9. ......
10. extend virtual task main_phase(uvm_phase phase);
11. ......
12. endclass
13.
14. function my_scb::new(string name="my_scb", uvm_component parent);
15. super.new(name);
16. endfunction:new
17.
18. function void my_scb::build_phase(uvm_phase phase);
19. super.build_phase(phase);
20. ......
21. scb_port = new("scb_port", this);
22. endfunction:build_phase
23.
24. ......
env代码:文章来源:https://www.toymoban.com/news/detail-718358.html
1. class my_env extend uvm_env;
2. my_mdl mdl;
3. my_scb scb;
4. uvm_tlm_analysis_fifo #(my_tr) rm2scb_fifo;
5.
6. `uvm_component_utils(my_env)
7.
8. extern function new(string name="my_env", uvm_component parent);
9. extern virtual function void build_phase(uvm_phase phase);
10. extern virtual function void connect_phase(uvm_phase phase);
11. ......
12. extern virtual task main_phase(uvm_phase phase);
13. ......
14. endclass
15.
16. function my_env::new(string name="my_env", uvm_component parent);
17. super.new(name);
18. endfunction:new
19.
20. function void my_env::build_phase(uvm_phase phase);
21. super.build_phase(phase);
22. mdl = my_mdl::type_id::create("mdl", this);
23. scb = my_scb::type_id::create("scb", this);
24. rm2scb_fifo = new("rm2scb_fifo", this);
25. endfunction:build_phase
26.
27. function void my_env::connect_phase(uvm_phase phase);
28. super.connect_phase(phase);
29. this.mdl.mdl_port.connect(rm2scb_fifo.blocking_put_export);
30. this.scb.scb_port.connect(rm2scb_fifo.blocking_get_export);
31. ......
32. endfunction:connect_phase
33. ......
这里的代码实例化FIFO以及连接的时候,没有使用for循环去例化,有点偷懒,读者可以自行补充这种情况的代码。文章来源地址https://www.toymoban.com/news/detail-718358.html
到了这里,关于UVM基础-TLM机制之analysis端口与FIFO的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!