Posts Tagged with "BSV"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.

BSV(Bluespec SystemVerilog) (2)

posted by sakurai on March 30, 2020 #229

BSV(Bluespec SystemVerilog)の解説

詳細はこちら(魚拓)

図229.1のような、3つのプロセスがレジスタx, yを更新する回路を設計することを考えます。この回路には、次のルール1から3までの、3つの仕様があります。

  • ルール1: cond2がアサートされると、プロセス2が起動しy--します。
  • ルール2: プロセス2が起動しないとき、かつcond1がアサートされると、プロセス1が起動しy++し、かつ同時にx--します。
  • ルール3: プロセス1が起動しないとき、かつcond0がアサートされると、プロセス0が起動しx++します。

補足するとルール2の場合、プロセス1が起動するときy++, x--は同時に起きるアトミックな演算です。つまり、プロセス1によるx--のみ、またはy++のみの実行は仕様違反となります。

図%%.1
図229.1 3つの並行プロセスにより書き換えられる2つのレジスタx, y
Verilogではステートに注目して記述します。
    always @ (posedge CLK) begin
        if (cond2)
            y <= y - 1;
        else if (cond1) begin
            y <= y + 1;
            x <= x - 1;
        end else if (cond0)
            x <= x + 1;
    end

このように記述したくなりますが、これだとcond2のアサート時にはxは書き換えられません。cond2アサートかつcond0アサートの場合は、ルール1とルール3が有効となるため、y--かつx++となるべきです。バグの原因は、優先順位(競合関係)が直接無いプロセス2と0に優先順位を持ち込んだことと考えて、alwaysの中を以下のように修正します。

        if (cond2)
            y <= y - 1;
        else if (cond1) begin
            y <= y + 1;

        if (cond1) begin
            x <= x - 1;
        end else if (cond0)
            x <= x + 1;

すると、今度は、プロセス1がプロセス0に勝ち、かつプロセス2に負けた時に、アトミック性が成立しません。ルール2が半分だけ実行されてしまいます。実はプロセス2と1は無関係ではなく、プロセス1を経由して関係が有ったのです。

ひとつの考え方としては、ハードでは並行に条件判定をするので、if else if 等とせずに、3本のif文を並べます。さらに外部信号cond1,2,3,でレジスタ更新を行うのではなく、プロセスの起動信号に注目します。具体的には、プロセス2の起動はcond2であるから、

    cond2

がプロセス2の起動条件です。プロセス1の起動は、そうではなく(!cond2)、かつ、cond1であるから、

    !cond2 && cond1

がプロセス1の起動条件です。プロセスの起動は、そうではなく(!(!cond2 && cond1))、かつ、cond0であるから、

    !(!cond2 && cond1) && cond0

がプロセス0の起動条件です。これらより、以下の記述が得られます。

        if (cond2)
            y <= y - 1;

        if (!cond2 && cond1) begin
            y <= y + 1;
            x <= x - 1;
        end 

        if (!(!cond2 && cond1) && cond0))
            x <= x + 1;

verilogでは優先順位を信号の条件で表すことで、複雑になっています。後からプロセスの優先順位が変わると、ハードコードされた条件文の修正が大変なことになります。

一方、VSBでは、レジスタの更新ルールがそのまま記述できます。

    rule proc0 (cond0);
        x <= x + 1;
    endrule

    rule proc1 (cond1);
        y <= y + 1;
        x <= x - 1;
    endrule

    rule proc2 (cond2);
        y <= y - 1;
    endrule
    (* descending_urgency = “proc2, proc1, proc0” *)

プロセスの優先順位と信号の条件が分離されているため、プロセスの優先順位が変わっても、コメントの修正のみでコードの修正はありません。

それでは、bscにより合成したverilogコードではどうなっているかというと、

    assign x$EN = WILL_FIRE_RL_proc0 || WILL_FIRE_RL_proc1 ;
    assign y$EN = WILL_FIRE_RL_proc1 || cond2 ;

    assign WILL_FIRE_RL_proc0 = cond0 && !WILL_FIRE_RL_proc1 ;
    assign WILL_FIRE_RL_proc1 = cond1 && !cond2 ;

レジスタxが変更されるのはx$ENがtrueの時、つまり、

    (cond0 && !(cond1 && !cond2)) || (cond1 && !cond2)

の時であり、レジスタyが変更されるのはy$ENがtrueの時、つまり、

    (cond1 && !cond2) || cond2

前述のverilogのifの中の条件と等価であることが分かります。

プロセスが3つ程度だとそれほど有難みがわかりませんが、これにプロセス3を一つ追加して、4つの優先順位を付けると、図229.2の赤字の修正のように、非常に複雑になります。

図%%.2
図229.2 4つの並行プロセスにより書き換えられる2つのレジスタx, y

左矢前のブログ 次のブログ右矢


ページ: