8

整数のオーバーフローがVHDLで定義されているかどうか疑問に思いました。2002年仕様では何も見つかりませんでした。

例として(注:これはコンパイルされない可能性があります。これは単なる一般的な例です...)

entity foo is port (
    clk : std_logic
);
end entity;

architecture rtl of foo is
    signal x : integer range 0 to 2 := 0;
begin
    process (clk)
    begin
        if rising_edge(clk) then
            x <= x + 1;
        end if;
    end process;
end architecture;

x0から1、次に2になることは明らかです。次の増分で何が起こるかが定義されていますか?それは未定義の動作ですか?

4

3 に答える 3

6

ghdlのfooのrtlのテストベンチの場合:

ghdl -r foo_tb --wave = foo_tb.ghw
./foo_tb:error:foo_tb.vhdl:15での境界チェックの失敗
./foo_tb:error:シミュレーションに失敗しました

Billのfooエンティティとアーキテクチャにコンテキスト句を追加しました。

library ieee;
use ieee.std_logic_1164.all;

entity foo is port (

15行目はxへの信号割り当てです。

            x <= x + 1;

これはシミュレーションエラーです(実行時に発生します)。

IEEE 1076-1993から:

7.2.4演算子の追加

加算演算子+および-は、任意の数値タイプに対して事前定義されており、従来の数学的意味を持っています。

これは、「+」演算子の結果がxのサブタイプ制約の外にある可能性があることを意味します。「+」にオーバーロードを提供するように宣言された関数は、結果のサブタイプを指定できないことに注意してください。(戻り値は、値の範囲または配列の長さを定義できるサブタイプ指示で宣言されたオブジェクトである可能性があります)。

および12.6.2信号値の伝播

特定のシミュレーションサイクル中に信号を更新するために、カーネルプロセスは最初にその信号の駆動値と実効値を決定します。次に、カーネルプロセスは、信号の現在の値を含む変数を、新しく決定された実効値で次のように更新します。

a)Sが配列型ではないタイプの信号である場合、Sの実効値を使用してSの現在の値を更新します。Sの実効値がSのサブタイプに属していることを確認します。このサブタイプチェックが失敗するとエラーが発生します。最後に、Sの実効値が、信号の現在の値を表す変数に割り当てられます。

加算の結果がターゲットxのサブタイプ制約と一致しない場合、エラーが生成されます。そのサブタイプ制約は、整数(範囲)のサブタイプ指示を提供するオブジェクトx宣言​​によって提供されます。

実行時エラーにより、LRM準拠の実装のシミュレーションが終了します。

エラーレポートの標準化されたフォーマットがないと、ghdlは現在のシミュレーション時間を提供しません。これは、生成された波形を調べることで見つけることができます。

foo_tb.png

波形は20ns後にかなり更新されています。次に予定されているイベント:

library ieee;
use ieee.std_logic_1164.all;

entity foo_tb is
end entity;

architecture foo of foo_tb is
    signal clk: std_logic := '0';
begin
DUT:
    entity work.foo
        port map (
            clk => clk
        );
        
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if now > 30 ns then
            wait;
        end if;
    end process;
    
end architecture;

25nsでのclkの立ち上がりエッジでした。

したがって、これは、制約された整数がどのようにオーバーフローエラーを生成するかを示しています。

サブタイプ制約のない整数はどうですか?

architecture fum of foo is
    signal x : integer := INTEGER'HIGH - 2;
begin
    process (clk)
    begin
        if rising_edge(clk) then
            x <= x + 1;
        end if;
    end process;
end architecture;

xを制約のない整数セットとして定義し、xがオーバーフローすると予想されるデフォルト値を設定します。

パッケージ標準は明示的にINTEGER"+"を宣言します:

--  function "+"      (anonymous, anonymous: INTEGER) return INTEGER;

「+」が通常の数学的意味を持っている場合、期待される結果はINTEGERの範囲外です。

ただし、パッケージ標準の実装依存宣言から:

type integer is range -2147483648 to 2147483647;

とシミュレーション:

foo_tb_wrap_around.png

xラップアラウンドの値がわかります。

「+」演算子の結果の割り当ては、制約に違反していません。

3種類:

特定のタイプのオブジェクトの可能な値のセットは、制約と呼ばれる条件に従うことができます(制約が制限を課さない場合も含まれます)。対応する条件を満たす場合、値は制約を満たすと言われます。サブタイプは、制約を伴うタイプです。値がそのタイプに属し、制約を満たしている場合、その値は特定のタイプのサブタイプに属していると言われます。指定されたタイプは、サブタイプの基本タイプと呼ばれます。タイプはそれ自体のサブタイプです。このようなサブタイプは制約なしと呼ばれます(制限を課さない条件に対応します)。タイプの基本タイプはタイプ自体です。

2番目のアーキテクチャでは、制約はありませんが、INTEGER型の宣言された範囲外の可能な値はありません。代わりに、値がロールオーバーします。

VHDLのセマンティクスは、ここでの検出を必要としないように構築されており、これは、バイナリビット(ハードウェア)を表す要素の1次元配列に対する数学演算と一致します。

于 2012-11-20T23:06:51.523 に答える
3

まともなシミュレーターは、オーバーフローした加算を正確に指すエラーメッセージでそこで停止します。(ザイリンクスIsimは、前回チェックをオンにしたことを覚えている場合は、まともなシミュレーターにすぎません)

何年にもわたってCプログラミングをやりすぎたら、不気味です!

合成はハードウェアを節約するために何でも行います(この場合、出力なしで、Xとプロセスを完全に最適化します!)ので、シミュレーションでこの種のバグをキャッチするのが最善です。

于 2012-11-19T08:53:33.910 に答える
2

整数のオーバーフロー(およびアンダーフロー)は、VHDLの実装定義の動作です。現時点では仕様を引用することはできませんが、よく読むと、整数範囲に関するほとんどすべてが、サポートされている最小範囲(-2**312**31)を超えて実装定義されていることがわかります。

32ビットマシンでのほとんどのVHDL実装は、実際には32ビット2の完全整数であるかのように動作し(たとえば、これらのプラットフォームでのマシン整数の動作)、64ビット実装は通常64ビット整数ですが、これを当てにすることはできません。 。

特定の例では、範囲のある整数サブタイプを使用している場合、その範囲外の値を割り当てようとするとエラーになり、実行時にアサーションが生成されます。(一方、シンセサイザーは、必要な奇妙なことを実行します。通常、シンセサイザーは2の補数の整数であるかのようにオーバーフローします)。

于 2012-11-19T04:51:29.100 に答える