プロトタイプ
プロトタイプは特別なジェネリック境界で、ジェネリックパラメータに渡せるプロトタイプを示します。現在はモジュールプロトタイプ、インターフェースプロトタイプ、パッケージプロトタイプがサポートされています。
モジュールプロトタイプ
以下の例では、ProtoA
がパラメータ A
とポート i_dat
o_dat
を持つモジュールプロトタイプです。T: ProtoA
のように制約することで、ジェネリックパラメータ T
がそれらのパラメータとポートを持つ必要があることが示されます。
プロトタイプを使うには for
による実装が必要です。ModuleC
と ModuleD
は for ProtoA
指定により、 ProtoA
の条件を満たすことが示されています。これにより、それらのモジュールは ModuleB
の ジェネリックパラメータ T
として使用できるようになります。
module ModuleA {
inst u0: ModuleB::<ModuleC>;
inst u1: ModuleB::<ModuleD>;
}
proto module ProtoA #(
param A: u32 = 1,
) (
i_dat: input logic,
o_dat: output logic,
);
module ModuleB::<T: ProtoA> {
inst u: T (
i_dat: 0,
o_dat: _,
);
}
module ModuleC for ProtoA #(
param A: u32 = 1,
) (
i_dat: input logic,
o_dat: output logic,
) {
assign o_dat = i_dat;
}
module ModuleD for ProtoA #(
param A: u32 = 1,
) (
i_dat: input logic,
o_dat: output logic,
) {
assign o_dat = ~i_dat;
}
インターフェースプロトタイプ
以下の例では、ProtoA
が定数 A
と変数 raedy
/valid
/data
、関数 ack
、modport master
を持つインターフェースプロトタイプです。BUS_IF
は ProtoA
で制約されているので、それらのメンバーを持つことが保証されており、参照することができます。
proto interface ProtoA {
const WIDTH: u32;
var ready: logic ;
var valid: logic ;
var data : logic<WIDTH>;
function ack() -> logic ;
modport master {
ready: input ,
valid: output,
data : output,
ack : import,
}
}
interface InterfaceA::<W: u32> for ProtoA {
const WIDTH: u32 = W;
var ready: logic ;
var valid: logic ;
var data : logic<WIDTH>;
function ack () -> logic {
return ready && valid;
}
modport master {
ready: input ,
valid: output,
data : output,
ack : import,
}
}
module ModuleA::<BUS_IF: ProtoA> (
bus_if: modport BUS_IF::master,
) {
connect bus_if <> 0;
}
module ModuleB {
inst bus_if: InterfaceA::<8>;
inst u: ModuleA::<InterfaceA::<8>> (
bus_if: bus_if,
);
}
パッケージプロトタイプ
以下の例では、ProtoA
が型 data_a
と型 data_b
を持つパッケージプロトタイプです。PKG
は ProtoA
で制約されているので、data_a
と data_b
を持つことが保証されており、それらを参照することができます。
proto package ProtoA {
type data_a;
type data_b;
}
package PackageA::<A: u32, B: u32> for ProtoA {
type data_a = logic<A>;
type data_b = logic<B>;
}
module ModuleA::<PKG: ProtoA> {
let _a: PKG::data_a = 0;
}
プロトタイプの要素
以下の要素はモジュール、インターフェース、パッケージのプロトタイプ内で宣言することができます。
テーブルにどのプロトタイプがどの要素を持てるかをまとめます。
プロトタイプ | パラメータ | ポート | 定数 | 変数 | 型定義 | 構造体/列挙型/ユニオン | 関数 | エイリアス | modport |
---|---|---|---|---|---|---|---|---|---|
モジュール | v | v | |||||||
インターフェース | v | v | v | v | v | v | |||
パッケージ | v | v | v | v | v |
パラメータ
パラメータプロトタイプは識別子とデータ型、デフォルト値を指定します。
proto module ModuleA #(
param A: u32 = 0,
param B: u32 = 1,
);
ポート
ポートプロトタイプは識別子と方向、データ型を指定します。
proto module ModuleA (
i_d: input logic,
o_d: output logic,
);
定数
定数プロトタイプは識別子とデータ型を指定します。ジェネリックなパラメータのプレースホルダとして使用できます。
proto package ProtoPkg {
const WIDTH: u32;
}
package PkgA::<W: u32> for ProtoPkg {
const WIDTH: u32 = W;
}
変数
変数プロトタイプは識別子とデータ型を指定します。これらは var
及び let
宣言で使用することができます。
proto interface ProtoA {
var a: logic;
var b: logic;
}
interface InterfaceA for ProtoA {
var a: logic;
let b: lgoic = 0;
}
型定義
Typedefプロトタイプは型エイリアスの識別子を指定します。ジェネリックなパラメータのプレースホルダとして使用できます。
proto package ProtoPkg {
type data_t;
}
package PkgA::<W: u32> for ProtoPkg {
type data_t = logic<W>;
}
構造体/列挙型/ユニオン
構造体、列挙型、ユニオンプロトタイプは型の識別子と各メンバーの識別子、データ型を指定します。
proto package ProtoPkg {
struct Foo {
a: logic,
b: logic,
}
enum Bar {
C,
D,
}
union Baz {
e: logic,
f: logic,
}
}
関数
関数プロトタイプは識別子と戻り値のデータ型、引数の方向とデータ型を指定します。
proto package ProtoPkg {
function foo (a: input logic, b: input logic) -> logic;
}
モジュール/インターフェース/パッケージ エイリアス
モジュール、インターフェース、パッケージのエイリアス プロトタイプは識別子とモジュール、インターフェース、パッケージのプロトタイプを指定します。そのエイリアスの実際の型は与えられたプロトタイプに制約されます。
proto module ProtoRamWrapper;
proto package ProtoPkg {
alias module ram: ProtoRamWrapper;
}
package Pkg::<RAM: ProtoRamWrapper> for ProtoPkg {
alias module ram = RAM;
}
module RamWrapper for ProtoRamWrapper {}
module top {
inst u_ram: Pkg::<RamWrapper>::ram;
}
modport
modport プロトタイプはmodport の識別子と各メンバーの識別子と方向を指定します。
proto interface ProtoA {
var a: logic;
var b: logic;
modport mp {
a: input ,
b: output,
}
}