TLM的put
my_case的main_phase中设定了raise_objection,并延时1000仿真单位后,drop,后续代码中的main_phase不设定raise和drop。
TLM的demo,(port->export->imp)
在A和B之间通信,首先在env中构建对应的实例(在不同的phase中),
然后给连接,A的port给数据到B的export中。
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); A_inst.A_port.connect(B_inst.B_export);
A中,
定义port,使用put发送。
uvm_blocking_put_port#(my_transaction) A_port; A_port = new("A_port", this); tr = new("tr"); assert(tr.randomize()); A_port.put(tr);
B中,
定义export,imp,进行连接,使用imp接收,其中imp连接到其put函数,最终连接到B的put函数。
uvm_blocking_put_export#(my_transaction) B_export; uvm_blocking_put_imp#(my_transaction, B) B_imp; B_export = new("B_export", this); B_imp = new("B_imp", this); B_export.connect(B_imp); function void B::put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) tr.print(); endfunction
port->imp
env中连接
A_inst.A_port.connect(B_inst.B_imp);
A不变
uvm_blocking_put_port#(my_transaction) A_port; A_port = new("A_port", this); tr = new("tr"); assert(tr.randomize()); A_port.put(tr);
B只有imp,然后是put函数
uvm_blocking_put_imp#(my_transaction, B) B_imp; B_imp = new("B_imp", this); function void B::put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) tr.print(); endfunction
注意:blocking_put类型,使用了put函数。如果是nonblocking_put,使用需要try_put和can_put两个函数;如果只有put,则需要以上三个函数。
如果为get类型,则需要对应的get函数。peek同理。get和peek同时(如blocking_get_peek),则同样结合二者需要的函数定义。
如果为transport,对应transport函数,非阻塞使用nb_transport函数。
阻塞部分不仅可以定义成函数,还可以定义成任务。
export->imp
env中,
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); A_inst.A_export.connect(B_inst.B_imp);
A中,
main_phase中为什么不用raise_objection
uvm_blocking_put_export#(my_transaction) A_export; A_export = new("A_export", this); tr = new("tr"); assert(tr.randomize()); A_export.put(tr);
B不变
uvm_blocking_put_imp#(my_transaction, B) B_imp; B_imp = new("B_imp", this); function void B::put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) tr.print(); endfunction
port->port->imp
C的port发送给A的port,然后A的port发送给B的imp
env中,
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); A_inst.A_port.connect(B_inst.B_imp);
C中,
uvm_blocking_put_port#(my_transaction) C_port; C_port = new("C_port", this); task C::main_phase(uvm_phase phase); my_transaction tr; repeat(10) begin #10; tr = new("tr"); assert(tr.randomize()); C_port.put(tr); end endtask
A中,
由谁发出数据,就由谁作为主动连接的connect调用。
C C_inst; uvm_blocking_put_port#(my_transaction) A_port;
A_port = new("A_port", this); C_inst = C::type_id::create("C_inst", this); C_inst.C_port.connect(this.A_port);
B中,不变
uvm_blocking_put_imp#(my_transaction, B) B_imp; B_imp = new("B_imp", this); function void B::put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) tr.print(); endfunction
port->export->export->imp
env中,
A A_inst; C C_inst; A_inst = A::type_id::create("A_inst", this); C_inst = C::type_id::create("B_inst", this); A_inst.A_port.connect(C_inst.C_export);
A中,
uvm_blocking_put_port#(my_transaction) A_port; A_port = new("A_port", this); tr = new("tr"); assert(tr.randomize()); A_port.put(tr);
C中,
B B_inst; uvm_blocking_put_export#(my_transaction) C_export; C_export = new("C_export", this); B_inst = B::type_id::create("B_inst", this); this.C_export.connect(B_inst.B_export);
B中,
uvm_blocking_put_export#(my_transaction) B_export; uvm_blocking_put_imp#(my_transaction, B) B_imp; B_export = new("B_export", this); B_imp = new("B_imp", this); B_export.connect(B_imp); function void B::put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) tr.print(); endfunction
TLM的get、transport、non_blocking
(get)A的imp->export->B的port(数据流向)
B为动作的发起者,A为被动从imp发送数据的动作接收者(B的port,A的export,A的imp控制流向)
imp作为动作的最终点。
my_env中,
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); B_inst.B_port.connect(A_inst.A_export);
B中,
uvm_blocking_get_port#(my_transaction) B_port; B_port = new("B_port", this); B_port.get(tr); `uvm_info("B", "get a transaction", UVM_LOW) tr.print();
A中,
uvm_blocking_get_export#(my_transaction) A_export; uvm_blocking_get_imp#(my_transaction, A) A_imp; my_transaction tr_q[$]; A_export = new("A_export", this); A_imp = new("A_imp", this); A_export.connect(A_imp); task A::get(output my_transaction tr); while(tr_q.size() == 0) #2; tr = tr_q.pop_front(); endtask task A::main_phase(uvm_phase phase); my_transaction tr; repeat(10) begin #10; tr = new("tr"); tr_q.push_back(tr); end endtask
(transport)A的transport->B的imp(数据双向)
动作从A->B
在env中,
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); A_inst.A_transport.connect(B_inst.B_imp);
在A中,
uvm_blocking_transport_port#(my_transaction, my_transaction) A_transport; A_transport = new("A_transport", this); task A::main_phase(uvm_phase phase); my_transaction tr; my_transaction rsp; repeat(10) begin #10; tr = new("tr"); assert(tr.randomize()); A_transport.transport(tr, rsp); `uvm_info("A", "received rsp", UVM_MEDIUM) rsp.print(); end endtask
在B中,
uvm_blocking_transport_imp#(my_transaction, my_transaction, B) B_imp; B_imp = new("B_imp", this); task B::transport(my_transaction req, output my_transaction rsp); `uvm_info("B", "receive a transaction", UVM_LOW) req.print(); //do something according to req #5; rsp = new("rsp"); endtask
non_blocking通信。A的port->B的imp
env中,常规
A A_inst; B B_inst; A_inst = A::type_id::create("A_inst", this); B_inst = B::type_id::create("B_inst", this); A_inst.A_port.connect(B_inst.B_imp);
A中,
可以直接使用try_put即可,附带了判断功能,通过则直接发送
uvm_nonblocking_put_port#(my_transaction) A_port; A_port = new("A_port", this); task A::main_phase(uvm_phase phase); my_transaction tr; repeat(10) begin tr = new("tr"); assert(tr.randomize()); while(!A_port.can_put()) #10; void'(A_port.try_put(tr)); end endtask
B中,
需要定义can_put和try_put函数。然后接收过程中,使用非阻塞(获取数据暂存队列),然后调用队列。
uvm_nonblocking_put_imp#(my_transaction, B) B_imp; my_transaction tr_q[$]; B_imp = new("B_imp", this); function bit B::can_put(); if(tr_q.size() > 0) return 0; else return 1; endfunction function bit B::try_put(my_transaction tr); `uvm_info("B", "receive a transaction", UVM_LOW) if(tr_q.size() > 0) return 0; else begin tr_q.push_back(tr); return 1; end endfunction task B::main_phase(uvm_phase phase); my_transaction tr; while(1) begin if(tr_q.size() > 0) tr = tr_q.pop_front(); else #25; end endtask
analysis的port