Prototype

Prototype is a special generic bound. It represents prototype which can be passed to the generic parameter. Currently module prototype, interface prototype and package prototype are supported.

Module Prototype

In the following example, ProtoA is a module prototype which has parameter A and port i_dat and o_dat. By binding like T: ProtoA, it is represented that the generic parameter T should have the parameters and ports.

To use prototype, for implementation is required. ModuleC and ModuleD have for ProroA specifier which means the module satisfies the condision of ProroA. So the modules can be used as the generic parameter T of ModuleB.

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

Interface Protype

In the following exmaple, ProtoA is a interface prototype which has constant A, raedy/valid/data variables, function ack and mopdort master. BUS_IF is restricted by ProtoA is guaranteed to have the above members, so they can be referred.

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

Package Prototype

In the following example, ProtoA is a package prototype which has type data_a and data_b. PKG restricted by ProtoA is guaranteed to have data_a and data_b, so they can be refered.

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

Prototype Items

Following protoype items can be declaraed within module, interface and package protoype declarations.

The following table shows which prototypes can have which prototype items.

PrototypeParameterPortConstVariableTypedefStruct/Enum/UnionFunctionAliasModport
Modulevv
Interfacevvvvvv
Packagevvvvv

Parameter

Parameter prototype specifies identifier name, data type and default value of a parameter.

proto module ModuleA #(
    param A: u32 = 0,
    param B: u32 = 1,
);

Port

Port prototype specifies identifier name, direction and data type of a port.

proto module ModuleA (
    i_d: input  logic,
    o_d: output logic,
);

Const

Const prototype specify identifier name and data type of a constant. It can be used as a placeholder of a generic parameter.

proto package ProtoPkg {
    const WIDTH: u32;
}
package PkgA::<W: u32> for ProtoPkg {
    const WIDTH: u32 = W;
}

Variable

Variable prototype specifies identifier name and data type of a variable. It can be used for both of var and let declarations.

proto interface ProtoA {
    var a: logic;
    var b: logic;
}
interface InterfaceA for ProtoA {
    var a: logic;
    let b: lgoic = 0;
}

Typedef

Typedef prototype specifies identifier name of a type alias. It can be used as a placeholder for a generic parameter.

proto package ProtoPkg {
    type data_t;
}
package PkgA::<W: u32> for ProtoPkg {
    type data_t = logic<W>;
}

Struct/Enum/Union

Struct, Enum and Union prototypes specify identifier name of a struct/enum/union and identifier name and data type of each members.

proto package ProtoPkg {
    struct Foo {
        a: logic,
        b: logic,
    }

    enum Bar {
        C,
        D,
    }

    union Baz {
        e: logic,
        f: logic,
    }
}

Function

Function prototype specifies identifier name and return data type of a function, and direction and data type of each arguments.

proto package ProtoPkg {
    function foo (a: input logic, b: input logic) -> logic;
}

Alias Module/Interface/Package

Module alias prototype, interface alias prototype and package alias protoype specify identifier name and prototype of a module/interface/pacakge alias. Type of an actual alias is restricted by the given prototype.

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 prototype specifis identifier name of a modport, and identifier name and direction of each membres.

proto interface ProtoA {
    var a: logic;
    var b: logic;

    modport mp {
        a: input ,
        b: output,
    }
}