一方通行のコミュニケーション(重要)

目次

1. 概要 (現状のアプリケーションシナリオのほとんどは一方向通信です)

2.方法

3. 例

4. まとめ(重要)

1. 概要 (現状のアプリケーションシナリオのほとんどは一方向通信です)

一方向通信とは、イニシエーターからターゲットへのデータ フローが一方向であること、またはイニシエーターとターゲットがプロデューサーとコンシューマーのいずれかの役割しか果たせないことを意味します。

UVM では、単一のデータ フローに対してさまざまなタイプの TLM ポートがあります。

uvm_blocking_put_PORT
uvm_nonblocking_put_PORT
uvm_put_PORT
uvm_blocking_get_PORT
uvm_nonblocking_get_PORT
uvm_get_PORT
uvm_blocking_peek_PORT
uvm_nonblocking_peek_PORT
uvm_peek_PORT
uvm_blocking_get_peek_PORT
uvm_nonblocking_get_peek_PORT
uvm_get_peek _ポート

このうち PORT は、port、export、imp の 3 つのポート名を表します。

UVM ポート名の命名規則によれば、これらは通信の 2 つの要素を示します。

  • ブロック方式ですか (つまり、遅延を待つことができます)
  • どのような通信メソッドですか(イニシエータはターゲット側で宣言したメソッドを呼び出したい)

put と get の具体的な違いは次のとおりです。

ピークと取得は、データがバフから取得されず、データがバフから削除されないことを除いて、同じ方向に流れます。

2.方法

ブロッキング トランスポートは関数名の一部としてブロッキング プレフィックスを使用しますが、非ブロッキング トランスポートはノンブロッキングという名前が付けられます。ブロッキング ポートのメソッド タイプはタスクであり、イベントの待機と遅延を確実に実現できます。非ブロッキング ポートのメソッド タイプは関数であり、メソッド呼び出しがすぐに返されることが保証されます。
ブロッキング送信をブロックする方法:

  • put(): イニシエータ氏はデータ T t を生成し、同時にターゲットにデータを送信します。
  • get(): イニシエータはターゲットからデータ T t を取得し、ターゲット内のデータ T t を消費する必要があります。
  • Peak(): イニシエータはターゲットからデータ T t を取得し、ターゲット内のデータ T t は保持される必要があります。

ノンブロッキングノンブロッキング転送方式:

  • try_put()
  • can_put()
  • try_get()
  • 取得することができます()
  • try_peek()
  • can_peek()

3. 例

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_blocking_put_port #(itrans) bp_port;      // #(itrans)是声明的参数类型
	uvm_nonblocking_get_port #(otrans) nbg_port;
	`uvm_component_utils(comp1)
	...
	task run_phase(uvm_phase phase);
		itrans itr;
		otrans otr;
		int trans_num = 2;
		fork
        //*************  fork 中用了两个线程***************
			begin
				for(int i = 0; i < trans_num; i++) begin
					itr = new("itr", this);
					itr.data = 'h10 + i;
					this.bp_port.put(itr);  
                   //目前只知道发送transaction,但不知道往哪个组件发送
                   //也看不出是调用组件2中的put方法
					`uvm_info("PUT", $sformatf("put itrans id: 'h%0x, data: 'h%0x", itr.id, itr.data), UVM_LOW)
				end
			end
			begin
				for(int j = 0; j < trans_num; j++) begin
					forever begin
						if(this.nbg_port.try_get(otr) == 1) break;
						else #1ns;
					end
					`uvm_info("TRYGET", $sformatf("get otrans id: 'h%0x, data: 'h%0x", otr.id, otr.data), UVM_LOW)
				end
			end
		join
	endtask
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_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_port.connect(c2.bp_imp);
		c1.nbg_port.connect(c2.nbg_imp);
	endfunction
endclass

4. まとめ(重要)

  1. 次の転送タイプを知るには
  2. 2 つのコンポーネントによって宣言されたインターフェイスは一致している必要があります。つまり、コンポーネント 1 とコンポーネント 2 のインターフェイスは両方とも blocking_put_port または nonblocking_get_port である必要があります。送信するデータの種類も一貫している必要があります。
  3. ターゲット側でput、try_get、can_getを実装する 
  4. 対応するポートを接続し、最上位環境にインポートします。接続ポリシーはイニシエーターであり、右側がターゲットであることに注意してください。

おすすめ

転載: blog.csdn.net/Arvin_ing/article/details/127707025