プロトタイプ

プロトタイプは特別なジェネリック境界で、ジェネリックパラメータに渡せるプロトタイプを示します。現在はモジュールプロトタイプ、インターフェースプロトタイプ、パッケージプロトタイプがサポートされています。

モジュールプロトタイプ

以下の例では、ProtoA がパラメータ A とポート i_dat o_dat を持つモジュールプロトタイプです。T: ProtoA のように制約することで、ジェネリックパラメータ T がそれらのパラメータとポートを持つ必要があることが示されます。

プロトタイプを使うには for による実装が必要です。ModuleCModuleDfor 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_IFProtoA で制約されているので、それらのメンバーを持つことが保証されており、参照することができます。

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 を持つパッケージプロトタイプです。PKGProtoA で制約されているので、data_adata_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
モジュールvv
インターフェースvvvvvv
パッケージvvvvv

パラメータ

パラメータプロトタイプは識別子とデータ型、デフォルト値を指定します。

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,
    }
}