12

この質問は UVM 固有のものではありませんが、私が取り組んでいる例は UVM 関連です。UVM 環境に一連のエージェントがあり、それらすべてに対してシーケンスを並行して起動したいと考えています。

私が以下を行う場合:

foreach (env.agt[i])
  begin
    seq.start(env.agt[i].sqr);
  end

の場合、シーケンスseqは最初に で実行されenv.agt[0].sqrます。それが終わったら、それを実行しenv.agt[1].sqrます。

すべてのシーケンサーseqで並列に実行されるように、foreach-fork ステートメントを実装したいと考えています。agt[i]

fork-join と foreach をどのように注文しても、それを達成することはできません。並列シーケンスの起動動作を取得するのを手伝ってもらえますか?

ありがとう。

私が解決しようとしている問題を明確にするための更新: 以下のコード構成の結果は、fork-join なしで上記とまったく同じです。


foreach (env.agt[i])
  fork
    seq.start(env.agt[i].sqr);
  join


fork
  foreach (env.agt[i])
    seq.start(env.agt[i].sqr);
  join


// As per example in § 9.3.2 of IEEE SystemVerilog 2012 standard
for (int i=0; i<`CONST; ++i)
  begin
    fork
      automatic int var_i = i;
      seq.start(env.agt[var_i].sqr);
    join
  end

4

4 に答える 4

2

これにアプローチするより「UVM」な方法は、仮想シーケンスを使用することだと思います。エージェント シーケンサーの配列をインスタンス化する仮想シーケンサーが既にあると仮定すると、仮想シーケンスの本体は次のようになります。

fork
  begin: isolation_thread
    foreach(p_sequencer.agent_sqr[i])
      automatic int j = i;
      fork
        begin
          `uvm_do_on(seq, p_sequencer.agent_sqr[j]);
        end
      join_none
    end
    wait fork;
  end: isolation_thread
join

これは過去に私のために働いていました。

于 2013-11-07T12:32:21.957 に答える
1

以下の Greg のソリューションは、UVM ベースの問題の解決策を導き出すのに役立ちました。これが私の解決策です:

以下の fork-join ブロックは、テスト ケース クラスの main_phase タスクにあります。wait fork;ステートメントは、そのスコープ (= foreach_fork begin-end ブロック) 内のすべての fork ステートメントが終了するのを待ってから、先に進みます。注意すべき重要な点はwait fork;、foreach_fork ブロックのスコープを設定するために、begin-end を fork-join でラップする必要があることです。


fork 
  foreach_fork : begin
    seq_class seq [`CONST];
    foreach(env.agt[i])
      begin
        int j = i;
        seq[j] = seq_class::type_id::create
                  (.name($sformatf("seq_%0d", j)), .contxt(get_full_name()));
        fork
          begin
            seq[j].start(env.agt[j].sqr);
          end
        join_none // non-blocking thread
      end
    wait fork;
  end : foreach_fork
join

シムの終了を遅らせるために順番に反論を利用する代替ソリューション。


begin
  seq_class seq [`CONST];
  foreach(env.agt[i])
    begin
      int j = i;
      seq[j] = seq_class::type_id::create
                (.name($sformatf("seq_%0d", j)), .contxt(get_full_name()));
      fork
        begin
          seq[j].starting_phase = phase;
          seq[j].start(env.agt[j].sqr);
        end
      join_none // non-blocking thread
    end
end

並行して実行したい seq ごとに新しいシーケンス オブジェクトを作成する必要があることにも気付きました。

System Verilog クラスのプロパティはデフォルトで自動であることを指摘してくれた Dave に感謝します。

代替ソリューションのメモ: 使用しなかったのでwait fork;、シーケンス自体で提起された UVM 異議を使用して、シミュレーション$finish呼び出しを延期します。シーケンスで反論を提起できるようにするために、私はseq[j].starting_phase = phase;構文を使用します。

于 2013-11-05T22:07:07.463 に答える
-1

で試してください

int i = 0
foreach (env.agt)
  begin
    seq.start(env.agt[i].sqr);
    i++;
end
于 2013-11-05T16:18:28.430 に答える