目录
系统原型,芯片验证

- class request extends uvm_transaction;
- byte cmd;
- int addr;
- int req;
- endclass
-
- class response extends uvm_transaction;
- byte cmd;
- int addr;
- int rsp;
- int status;
- endclass
-
- class comp1 extends uvm_agent;
- uvm_blocking_get_port #(request) bg_port;//port被数据流指向为get
- `uvm_component_utils(comp1)
- ...
- endclass
-
- class comp2 extends uvm_agent;
- uvm_blocking_get_port #(request) bg_port;
- uvm_nonblocking_put_imp #(request, comp2) nbp_imp;//imp被数据流指向为put
- `uvm_component_utils(comp2)
- ...
- function bit try_put (request req);
- function bit can_put();
- endclass
-
- class comp3 extends uvm_agent;
- uvm_blocking_transport_port #(request, response) bt_port;//双向端口transport
- `uvm_component_utils(comp3)
- ...
- endclass
-
- class comp4 extends uvm_agent;
- uvm_blocking_get_imp #(request, comp4) bg_imp;//发送数据流的imp是get
- uvm_nonblocking_put_port #(request) nbp_port;//发送数据流的port是put
- `uvm_component_utils(comp3)
- ...
- task get(output request req);
- endclass
-
- class comp5 extends uvm_agent;
- uvm_blocking_transport_imp #(request, response, comp5) bt_imp;//双向imp
- `uvm_component_utils(comp5)
- ...
- task transport(request req, output response rsp);
- endclass
-
- class agent1 extends uvm_agent;
- uvm_blocking_get_port #(request) bg_port;//从上往下依次对应3个端口
- uvm_nonblocking_put_export #(request) nbp_exp;
- uvm_blocking_transport_port #(request, response) bt_port;
- comp1 c1;
- comp2 c2;
- comp3 c3;
- `uvm_compontne_utils(agent1)
- ...
- function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- c1=comp1::type_id::create("c1", this);
- c2=comp2::type_id::create("c2", this);
- c3=comp3::type_id::create("c3", this);
- endfunction
-
- function void connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- c1.bg_port.connect(this.bg_port);//comp1的bg_port连到this agent上的bg_port
- c2.bg_port.connect(this.bg_port);//port连到export
- this.nbp_exp.connect(c2.nbp.imp);//export连到imp
单一数据流向的TLM端口类型
总结成表格如下:
uvm_
| put | get | peek | get_peek | |
|---|---|---|---|---|
| blocking(task) | ||||
| nonblocking(function) | ||||
| 无 |
_PORT=port/export/imp
对应的方法声明如下:

- class itrans extends uvm_transaction;
- int id;
- int data;
- endclass
-
- class otrans extends uvm_transaction;
- int id;
- int data;
- endclass
-
- class comp1 extends uvm_component;
- uvm_nonblocking_get_port #(otrans) nbg_port;//接收
- uvm_blocking_put_port #(itrans) bp_port;//发送数据
- `uvm_component_utils(comp1)
- ...
- endclass
-
- class comp2 extends uvm_component;
- uvm_blocking_put_imp #(itrans, comp2) bp_imp;
- uvm_nonblocking_get_imp #(otrans, comp2) nbg_imp;
- itrans itr_q[$];
- `uvm_component_utils(comp2)
- ...
- task put(itrans t);
- itr_q.push_back(t);
- endtask
-
- function bit try_get (output otrans t);
- itrans i;
- if(itr_q.size() != 0) begin
- i=itr_q.pop_front();
- t=new("t", this);
- t.id=i.id;
- t.data=i.data<<8;
- return 1; end
- else return 0;
- endfunction
-
- function bit can_get();
- if(itr_q.size()!=0) return 1;
- else return 0;
- endfunction
-
- endclass
-
- class env1 extends uvm_env;
- comp1 c1;
- comp2 c2;
- `uvm_component_utols(env1)
- ...
- function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- c1=comp1::type_id::create("c1", this);
- c2=comp2::type_id::create("c2", this);
- endfunction
-
- function void connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- c1.bp_port.connect(c2.bp_imp);
- c2.nbg_port.connect(c2.nbg_imp);
- endfunction
- endclass
-
- //................................................
- task run_phase(uvm_phase phase);
- itrans itr;
- otrans otr;
- int trans_num=2;
- fork
- begin
- for(int i=0; i
- itr=new("itr", this);
- itr.id=i;
- itr.data='h10+i;
- this.bp_port.put(itr);//连接的imp中定义的put()
- `uvm_info("PUT", $sformatf("'h%0x, 'h%0x", itr.id, itr.data), UVM_LOW) end
- end
- begin
- for(int j=0; j
- forever begin
- if(this.nbg.port.try_get(otr)==1) break;
- else #1ns; end
- `uvm_info("TRYGET", $sformatf("'h%0x, 'h%0x", otr.id, otr.data), UVM_LOW)
- end
- join
-
双向通信
- 双向端口
- uvm_blocking_transport_PORT
- uvm_nonblocking_transport_PORT
- uvm_transport_PORT
- uvm_blocking_master_PORT
- uvm_nonblocking_master_PORT
- uvm_master_PORT
- uvm_blocking_slave_PORT
- uvm_nonblocking_slave_PORT
- uvm_slave_PORT
transport master slave blocking(task) nonblocking(function) 无
对应的方法
- 两种通信方式
- transport:通过方法transport()完成req和rsp的发出和返回,1个方法完成1次握手
- master+slave:必须分别调用put、get、peek完成,调用两个方法完成1次握手通信
- initiator作为master时,发起req到target并获取rsp回来
- initiator作为slave时,从target获取req再发送rsp
实例

- class comp1 extends uvm_component;
- uvm_blocking_transport_port #(itrans, otrans) bt_port;
- `uvm_component_utils(comp1)
- ...
- task run_phase(uvm_phase phase);
- itrans itr;
- otrans otr;
- int trans_num=2;
- for (int i=0; i
- itr=new("itr", this);
- itr.id=i;
- itr.data='h10+i;
- this.bt_port.transport(itr, otr);
- `uvm_info("TRANSPORT", $sformatf("'h%0x, 'h%0x, 'h%0x, 'h%0x", itr.id, itr.data, otr.id, otr.data), UVM_LOW)
- end
- endtask
- endclass
-
- class comp2 extends uvm_component;
- uvm_blocking_transport_imp #(itrans, otrans, comp2) bt_imp;
- `uvm_component_utils(comp2)
- ...
- task transport(itrans req, output otrans rsp);
- rsp=new("rsp", this);
- rsp.id=req.id;
- rsp.data=req.data<<8;
- endtask
- endclass
-
- class env1 extends uvm_env;
- comp1 c1;
- comp2 c2;
- `uvm_component_utils(comp2)
- ...
- function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- c1=comp1::type_id::create("c1", this);
- c2=comp2::type_id::create("c2", this);
- endfunction
-
- function void connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- c1.bt_port.connect(c2.bt_imp);
- endfunction
- endclass
多向通信
- 两个组件之间的通信:initiator和target之间的相同TLM端口数量超过1个
- 问题:相同的端口,端口名字可以不一样,方法会出现同名的问题
- 方法:UVM端口宏声明(`上述端口类型_decl(SFX)),sfx表示后缀名称

- `uvm_blocking_put_imp_decl(_p1)
- `uvm_blocking_put_imp_decl(_p2)
- class comp1 extends uvm_component;
- uvm_blocking_put_port #(itrans) bt_port1;//不需要做区分
- uvm_blocking_put_port #(itrans) bt_port2;
- `uvm_component_utils(comp1)
- ...
- task run_phase(uvm_phase phase);
- itrans itr1, itr2;
- int trans_num=2;
- fork
- for (int i=0; i
- itr1=new("itr1", this);
- itr1.id=i;
- itr1.data='h10+i;
- this.bp_port1.put(itr1);//不是put_p1
- end
- for (int i=0; i
- itr2=new("itr2", this);
- itr2.id=i;
- itr2.data='h10+i;
- this.bp_port2.put(itr2);//不是put_p2
- end
- join
- endtask
- endclass
-
- class comp2 extends uvm_component;
- uvm_blocking_put_imp_p1 #(itrans, comp2) bt_imp_p1;
- uvm_blocking_put_imp_p2 #(itrans, comp2) bt_imp_p2;
- itrans itr_q[$];
- semaphore key;//共享资源,互斥资源的保护
- `uvm_component_utils(comp2)
- ...
- task put_p1(itrans t);
- key.get();
- itr_q.push_back(t);
- `uvm_info("PUTP1", $sformatf("'h%0x, 'h%0x", t.id, t.data), UVM_LOW)
- key.put();
- endtask
-
- task put_p2(itrans t);
- key.get();
- itr_q.push_back(t);
- `uvm_info("PUTP2", $sformatf("'h%0x, 'h%0x", t.id, t.data), UVM_LOW)
- key.put();
- endtask
-
- endclass
-
- class env1 extends uvm_env;
- comp1 c1;
- comp2 c2;
- `uvm_component_utils(env1)
- ...
- function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- c1=comp1::type_id::create("c1", this);
- c2=comp2::type_id::create("c2", this);
- endfunction
- function void connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- c1.bp_port1.conect(c2.bt_imp_p1);
- c1.bp_port2.conect(c2.bt_imp_p2);
- endfunction
-
- endclass
通信管道
uvm_tlm_fifo
- uvm_tlm_fifo类继承于uvm_component,内置了多个端口、实现了多个对应方法
- 作用:在consumer分析事务之前,将对象存储到本地fifo以供稍后使用
analysis port
- 一个端口到多个端口,多个组件对同一个数据进行处理
- 类比:广播,发出来后依次调用多个target中的write函数实现数据传输,不做任何反馈,也就是说,这个端口只管发出,不管别人接收到与否,类似于广播
- 类型:对应三种类型的端口
- 连接:在顶层将initiator端的aport和多个target端的uvm_analysis_imp进行连接

- initiator.ap.connect(target1.aimp);
- initiator.ap.connect(target2.aimp);
- initiator.ap.connect(target3.aimp);
analysis TLM FIFO
- uvm_tlm_analysis_fifo提供可以搭配uvm_analysis_port和uvm_analysis_imp端口和write函数
- uvm_tlm_analysis_fifo继承于uvm_tlm_fifo
- uvm_analysis_imp #(T, uvm_tlm_analysis_fifo #(T)) analysis_export;
- //端口类型是imp,只是名字是export
- 实现一端对多端的数据传输,插入多个uvm_tlm_analysis_fifo
- 连接方式:initiator的uvm_analysis port——tlm_analysis_fifo的get_export——target的uvm_get_port。从target调用get方法就可以得到tlm_analysis_fifo中的数据
- initiator.ap.conncet(tlm_analysis_fifo1.analysis_export);
- target1.get_port.connect(tlm_analysis_fifo1.get_export);
- //2和3以此类推

req&rsp通信管道
- 类比双向通信端口transport:在target端口实现transport()方法可以一次传输完成发送req+接收rsp
- 作用:数据缓存区域,既有TLM端口从外侧接收req和rsp,也有TLM端口供外侧获取req和rsp
- uvm_tlm_req_rsp_channel
- 例化的端口如下
- 内部例化了两个mailbox分别存储req和rsp
- protected uvm_tlm_fifo #(REQ) m_request_fifo;
- protected uvm_tlm_fifo #(RSP) m_response_fifo;

- uvm_put_export #(REQ) put_request_export;
- uvm_put_export #(RSP) put_response_export;
- uvm_get_peek_export #(REQ) get_peek_request_export;
- uvm_get_peek_export #(RSP) get_peek_response_export;
- uvm_analysis_port #(REQ) request_ap;
- uvm_analysis_port #(RSP) response_ap;
- uvm_master_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) master_export;
- uvm_slave_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) slave_export;
- initiator.put_port.connect(req_rsp_channel.put_request_export);
- target.get_peek_port.connect(req_rsp_channel.get_peek_request_export);
- target.put_port.connect(req_rsp_channel.put_response_export);
- initiator.get_peek_port.connect(req_rsp_channel.get_peek_response_export);
- 也可以用这种方式

- initiator.master_port.connect(req_rsp_channel.master_export);
- target.slave_port.connect(req_rsp_channel.slave_export);
-
但是,这两种方法都需要调用两次方法才可以完成req和rsp的传输
-
uvm_tlm_transport_channel继承于uvm_tlm_req_rsp_channel类
- 新例化了transport端口:uvm_transport_imp #(REQ, RSP, this_type) transport_export;
- 作用:针对一些无法流水化处理的req和rsp传输,initiator发送完req后等到rsp收到了才可以发送下一个req
- 上图的连接修改为:initiator.transport_port.connect(transport_channel.transport_export)。transport_channel到target之间的连接不做修改:target.slave_port.connect(req_rsp_channel.slave_export);
-
相关阅读:
用HTML+CSS仿网易云音乐网站(6个页面)
有手就行10——Jenkins+SonarQube代码审查
数据结构--单链表
网络爬虫之HTTP原理
什么是space-around
IP地址与代理ip在网络安全中的关键作用
【pen200-lab】10.11.1.231
Jenkins+Allure+Pytest的持续集成
CCF ChinaSoft 2023 论坛巡礼 | NASAC青年软件创新奖论坛
关于el-date-picker点击清空参数变为null的问题
-
原文地址:https://blog.csdn.net/weixin_39668316/article/details/125880955