型推論

型注釈やジェネリック引数は、周辺のコードから導出できる場合に省略できることがあります。この章ではサポートされるパターンをまとめます。

モジュール/インターフェース/関数のポート宣言や関数の戻り値型は、型が推論可能であっても、インターフェースを明確に保つため引き続き型注釈が必要です。

変数の型推論

varlet 宣言、および const 宣言の型注釈は、型が推論可能な場合に省略できます。

型を持たない var 宣言では、assignalways_combalways_ff を通じた最初の代入から型が推論されます。let および const 宣言では、右辺の式から型が推論されます。

module ModuleA {
    let _a: logic<8> = 0;

    // `_a` の型から推論される。
    let _b = _a;

    // ビット幅付きリテラルから推論される。
    let _c = 8'd255;

    // 最初の代入から推論される。
    var _d;
    assign _d = _a;

    // always_comb 内の最初の代入から推論される。
    var _e;
    always_comb {
        _e = _a;
    }

    // `const` も推論をサポートする。
    const _F = 16'd100;
}

以下の式は型推論の元として使用できます。

  • 変数参照
  • ビット幅付き数値リテラル(例: 8'd10
  • 括弧で囲まれた式(内側の式へ再帰的に推論)
  • 関数呼び出し(戻り値の型から推論)

以下の式は SystemVerilog のビット幅評価規則に依存し、ユーザーにとって予期しにくい結果になるため、サポートされません。

  • ビット幅なし数値リテラル(例: 10'0
  • 演算子を含む式(例: _a + 1
  • 連結(例: {_a, _a}
  • if / case

同一の var に対する複数の代入で推論される型が一致しない場合、type_inference_conflict として報告されます。サポートされていない式の場合は type_inference_not_supported が報告されます。いずれの場合も、明示的な型注釈を加えればエラーは解消されます。

ジェネリック引数の推論

ジェネリック関数では、関数の引数からジェネリック引数を推論できる場合、::<> 後の実引数を省略できます。推論は各実引数の宣言型を用いてジェネリックパラメータを解決します。

module ModuleA {
    function FuncId::<T: u32> (
        x: input logic<T>,
    ) -> logic<T> {
        return x;
    }

    function FuncWide::<T: u32> (
        x: input logic<T>,
    ) -> logic<T + 1> {
        return {1'b0, x};
    }

    let _a: logic<8>  = 0;
    let _b: logic<16> = 0;

    // 実引数の宣言された幅から T が 8 / 16 に推論される。
    let _r1: logic<8>  = FuncId(_a);
    let _r2: logic<16> = FuncId(_b);

    // `T + 1` パターン: 実引数の幅 8 から T = 8 が解決される。
    let _rw: logic<9> = FuncWide(_a);
}

実引数の幅を変数宣言から決定できない場合(例: ビット幅付きリテラルを渡した場合)、推論は失敗します。その場合は明示的なジェネリック引数が必要です。詳細は generic_inference_failed を参照してください。