跨层次的连接
通常情况下,一个验证环境中,并不一定所有的通讯都是建立在同层级的组件之间互联,相比之下,跨层级组件间的互联更为常见,想象一个场景,driver被想要发送一个tr给RM,要经过一层agent封装,才能将tr发送给RM,此时就出现了跨层级的访问,而port与port相连,export与export相连,为这种场景下的互联提供了解决方案。
- port与port的连接
如图3.3.4.1所示,port与port连接场景:
图3.3.4.1 port与port连接场景
如图3.3.4.1所示,组件A被例化到了组件C中,与外部组件B互联,而组件C和组件B被例化到了TOP中,想要实现组件A和组件B之间的通信,需要通过组件C的port端口,因此出现port和port之间的互联,通过代码说明:
组件A中代码:
1. class a extend uvm_component;
2. `uvm_component_utils(a)
3. uvm_blocking_put_port#(my_tr) a_port;
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_port = new("a_port", this);
12. ......
13. endfunction:build_phase
组件B中代码:
1. class b extend uvm_component;
2. `uvm_component_utils(b)
3. uvm_blocking_put_export#(my_tr) b_export;
4. uvm_blocking_put_imp# (my_tr, b) b_imp;
5. my_tr tr_q[$];
6. ......
7. extern function void build_phase(uvm_phase phase);
8. extern function void connect_phase(uvm_phase phase);
9. extern task put(my_tr tr);
10. ......
11. endclass
12.
13. function void b::build_phase(uvm_phase phase);
14. super.build_phase(phase);
15. b_export = new("b_export", this);
16. b_imp = new("b_imp", 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.b_export.connect(this.b_imp);
23. ......
24. endfunction:connect_phase
25.
26. task b::put(my_tr tr);
27. ......
28. wait process_tr_finish; //event
29. tr_q.push_front(tr);
30. tr.print();
31. endtask:put
在组件C中:
1. class c extend uvm_component;
2. `uvm_component_utils(c)
3. uvm_blocking_put_port#(my_tr) c_port;
4. a my_a;
5. ......
6. extern function void build_phase(uvm_phase phase);
7. extern function void connect_phase(uvm_phase phase);
8. ......
9. endclass
10.
11. function void c::build_phase(uvm_phase phase);
12. super.build_phase(phase);
13. my_a = a::type_id::create("my_a", this);
14. c_port = new("c_port", this);
15. ......
16. endfunction:build_phase
17.
18. function void c::connect_phase(uvm_phase phase);
19. super.connect_phase(uvm_phase phase);
20. this.my_a.a_port.connect(this.c_port);
21. ......
22. endfunction:connect_phase
上述代码块第20行可以发现,port端口只能由深层次的组件往外部连接,因此是深层次的组件通过connect函数,连接外部层次的port,即外部层次的port作为深层次port的connect函数的参数。连反的话会报错。
此处是通过调用connect函数实现的连接,也可以通过类的赋值实现,不实例化c_port,将其直接指向a的a_port,代码如下:
1. class c extend uvm_component;
2. `uvm_component_utils(c)
3. uvm_blocking_put_port#(my_tr) c_port;
4. a my_a;
5. ......
6. extern function void build_phase(uvm_phase phase);
7. extern function void connect_phase(uvm_phase phase);
8. ......
9. endclass
10.
11. function void c::build_phase(uvm_phase phase);
12. super.build_phase(phase);
13. my_a = a::type_id::create("my_a", this);
14. ......
15. endfunction:build_phase
16.
17. function void c::connect_phase(uvm_phase phase);
18. super.connect_phase(uvm_phase phase);
19. this.c_port = this.my_a.a_port;
20. ......
21. endfunction:connect_phase
该代码块与上述代码块相比,删除了c_port的实例化,将20行的连接关系改成了类的赋值,c_port直接指向了my_a.a_port。
最后,TOP代码块:
1. class TOP extend uvm_component;
2. `uvm_component_utils(TOP)
3. b my_b;
4. c my_c;
5. ......
6. extern function void build_phase(uvm_phase phase);
7. extern function void connect_phase(uvm_phase phase);
8. ......
9. endclass
10.
11. function void TOP::build_phase(uvm_phase phase);
12. super.build_phase(phase);
13. my_b = b::type_id::create("my_b", this);
14. my_c = c::type_id::create("my_c", this);
15. ......
16. endfunction:build_phase
17.
18. function void TOP::connect_phase(uvm_phase phase);
19. super.connect_phase(uvm_phase phase);
20. this.my_c.c_port.connect(this.my_b.b_export);
21. ......
22. endfunction:connect_phase
其实也可以直接在TOP跨层次直接将组件A的port与组件B的export相连,此时就无需通过组件C的port,代码较为简单,不在赘述。
- export与export的连接
如图3.3.4.2所示,export与export连接场景:
图3.3.4.2 export与export连接场景
如图3.3.4.2所示,组件B被例化到了组件C中,与外部组件A互联,而组件C和组件A被例化到了TOP中,想要实现组件A和组件B之间的通信,需要通过组件C的export端口,此时例化在组件C中的组件B和C之间互联就出现export和export之间的连接关系,通过代码说明:用transport类型端口举例说明。
组件A中代码:
14. class a extend uvm_component;
15. `uvm_component_utils(a)
16. uvm_blocking_transport_port#(my_tr, my_tr) a_port;
17. ......
18. extern function void build_phase(uvm_phase phase);
19. ......
20. endclass
21.
22. function void a::build_phase(uvm_phase phase);
23. super.build_phase(phase);
24. a_port = new("a_port", this);
25. ......
26. endfunction:build_phase
组件B中代码:
1. class b extend uvm_component;
2. `uvm_component_utils(b)
3. uvm_blocking_transport_export#(my_tr, my_tr) b_export;
4. uvm_blocking_transport_imp# (my_tr, my_tr, b) b_imp;
5. my_tr tr_q[$];
6. ......
7. extern function void build_phase(uvm_phase phase);
8. extern function void connect_phase(uvm_phase phase);
9. extern task transport(my_tr REQ, output my_tr RSP);
10. ......
11. endclass
12.
13. function void b::build_phase(uvm_phase phase);
14. super.build_phase(phase);
15. b_export = new("b_export", this);
16. b_imp = new("b_imp", 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.b_export.connect(this.b_imp);
23. ......
24. endfunction:connect_phase
25.
26. task b::transport (my_tr REQ, output my_tr RSP);
27. ......
28. //process REQ
29. tr_q.push_front(REQ);
30. REQ.print();
31. RSP = new("RSP");
32. RSP.data = 32'hffff_0000;
33. //Generate RSP pkt
34. endtask:transport
在组件B中,因为例化了transport类型的端口,因此需要在组件B中实现transport任务,收到一个REQ包后,要生成一个RSP包回传给动作发起者。
在组件C中:
23. class c extend uvm_component;
24. `uvm_component_utils(c)
25. uvm_blocking_transport_export#(my_tr, my_tr) c_export;
26. b my_b;
27. ......
28. extern function void build_phase(uvm_phase phase);
29. extern function void connect_phase(uvm_phase phase);
30. ......
31. endclass
32.
33. function void c::build_phase(uvm_phase phase);
34. super.build_phase(phase);
35. my_b = b::type_id::create("my_b", this);
36. c_export = new("c_export", this);
37. ......
38. endfunction:build_phase
39.
40. function void c::connect_phase(uvm_phase phase);
41. super.connect_phase(uvm_phase phase);
42. this.c_export.connect(this.my_b.b_export);
43. ......
44. endfunction:connect_phase
上述代码块第42行可以发现,export端口只能由外层次的组件往内部深层次组件连接,因此是外部层次的组件通过connect函数,连接内部神层次的export,即内部深层次的export作为外部层次export的connect函数的参数。连反同样会报错。
此处是通过调用connect函数实现的连接,也可以通过类的赋值实现,不实例化c_export,将其直接指向b的b_export,代码如下:
22. class c extend uvm_component;
23. `uvm_component_utils(c)
24. uvm_blocking_transport_export#(my_tr, my_tr) c_export;
25. b my_b;
26. ......
27. extern function void build_phase(uvm_phase phase);
28. extern function void connect_phase(uvm_phase phase);
29. ......
30. endclass
31.
32. function void c::build_phase(uvm_phase phase);
33. super.build_phase(phase);
34. my_b = b::type_id::create("my_b", this);
35. ......
36. endfunction:build_phase
37.
38. function void c::connect_phase(uvm_phase phase);
39. super.connect_phase(uvm_phase phase);
40. this.c_export = this.my_b.b_export;
41. ......
42. endfunction:connect_phase
该代码块与上述代码块相比,删除了c_export的实例化,将42行的连接关系改成了类的赋值,c_export直接指向了my_b.b_export。
最后,TOP代码块:
23. class TOP extend uvm_component;
24. `uvm_component_utils(TOP)
25. a my_a;
26. c my_c;
27. ......
28. extern function void build_phase(uvm_phase phase);
29. extern function void connect_phase(uvm_phase phase);
30. ......
31. endclass
32.
33. function void TOP::build_phase(uvm_phase phase);
34. super.build_phase(phase);
35. my_a = a::type_id::create("my_a", this);
36. my_c = c::type_id::create("my_c", this);
37. ......
38. endfunction:build_phase
39.
40. function void TOP::connect_phase(uvm_phase phase);
41. super.connect_phase(uvm_phase phase);
42. this.my_a.a_port.connect(this.my_c.c_export);
43. ......
44. endfunction:connect_phase
其实也可以直接在TOP跨层次直接将组件A的port与组件B的export相连,此时就无需通过组件C的export,代码较为简单,不在赘述。
- 总结
- port与port之间的互联,只能由深层次组件的port往外连接,连接上层次组件的port;
- export与export之间的互联,只能由上层次组件的export往更深层组组件的export连接;
- port和port之间的连接,export与export之间的连接,可以跨很多层次互联
- 互联组件的终点,一定是一个包含imp端口的组件。