ジェネリクス
ジェネリクスはパラメータオーバーライドでは実現できないアイテムのパラメータ化を可能にします。以下のアイテムがジェネリクスをサポートしています。
- 関数
- モジュール
- インターフェース
- パッケージ
- 構造体
- ユニオン
それぞれのジェネリック定義はジェネリックパラメータ(T
のような大文字1文字がよく使われます)を持ち、定義内で識別子や式として配置できます。ジェネリックパラメータはアイテムの識別子の後に ::<>
を用いて宣言します。
各ジェネリックパラメータにはコロンの後に T: const
のようなジェネリック境界が必要です。ジェネリック境界はどのような値をそのパラメータに渡すことができるかを示します。使用可能なジェネリック境界は以下の通りです。
const
: 定数値を渡すことができるtype
: 任意の型を渡すことができる- 名前付きプロトタイプ
名前付きプロトタイプは特別なジェネリック境界です。詳細は プロトタイプ を参照してください。
ジェネリクスを使用するためには ::<>
を用いて実パラメータを与えます。実パラメータとしては数値リテラルと ::
で連結された識別子を使用することができます。
さらに、実パラメータはジェネリクス定義位置から参照できなければなりません。例えば、モジュール名はプロジェクト全体から参照できるので、実パラメータとして使用できます。一方、ローカルパラメータは多くの場合、実パラメータとして使用できません。これはローカルパラメータがジェネリクス定義位置からは参照できない場合に発生します。
ジェネリック関数
module ModuleA {
function FuncA::<T: const> (
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>;
}
proto module ProtoA;
module ModuleB::<T: ProtoA> {
inst u: T;
}
module ModuleC for ProtoA {}
module ModuleD for ProtoA {}
ジェネリックパッケージ
module ModuleA {
const A: u32 = PackageA::<1>::X;
const B: u32 = PackageA::<2>::X;
}
package PackageA::<T: const> {
const X: u32 = T;
}
ジェネリック構造体
module ModuleA {
type TypeA = i32;
struct StructA::<T: type> {
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;
}