ジェネリクス

ジェネリクスはパラメータオーバーライドでは実現できないアイテムのパラメータ化を可能にします。以下のアイテムがジェネリクスをサポートしています。

  • 関数
  • モジュール
  • インターフェース
  • パッケージ
  • 構造体
  • ユニオン

それぞれのジェネリック定義はジェネリックパラメータ(T のような大文字1文字がよく使われます)を持ち、定義内で識別子や式として配置できます。ジェネリックパラメータはアイテムの識別子の後に ::<> を用いて宣言します。

ジェネリクスを使用するためには ::<> を用いて実パラメータを与えます。実パラメータとしては数値リテラルと :: で連結された識別子を使用することができます。

さらに、実パラメータはジェネリクス定義位置から参照できなければなりません。例えば、モジュール名はプロジェクト全体から参照できるので、実パラメータとして使用できます。一方、ローカルパラメータは多くの場合、実パラメータとして使用できません。これはローカルパラメータがジェネリクス定義位置からは参照できない場合に発生します。

ジェネリック関数

module ModuleA {
    function FuncA::<T> (
        a: input logic<T>,
    ) -> logic<T> {
        return a + 1;
    }

    let _a: logic<10> = FuncA::<10>(1);
    let _b: logic<20> = FuncA::<20>(1);
}

ジェネリックモジュール/インターフェース

module ModuleA {
    inst u0: ModuleB::<ModuleC>;
    inst u1: ModuleB::<ModuleD>;
}

module ModuleB::<T> {
    inst u: T;
}

module ModuleC {}
module ModuleD {}

ジェネリックパッケージ

module ModuleA {
    local A: u32 = PackageA::<1>::X;
    local B: u32 = PackageA::<2>::X;
}

package PackageA::<T> {
    local X: u32 = T;
}

ジェネリック構造体

module ModuleA {
    type TypeA = i32;

    struct StructA::<T> {
        A: T,
    }

    // ローカルに定位された型が使用できています
    // これは `TypeA` が `StructA` の定義位置から参照できるためです
    var _a: StructA::<TypeA>          ;
    var _b: StructA::<PackageA::TypeB>;
    var _c: StructA::<PackageA::TypeC>;
}

package PackageA {
    type TypeB = u32;
    type TypeC = u64;
}