アトリビュート
アトリビュートは変数宣言などいくつかの宣言に注釈を付けることができます。
sv アトリビュート
sv アトリビュートは SystemVerilog のアトリビュートを表し、(* *) という形式の SystemVerilog アトリビュートに変換されます。
module ModuleA {
#[sv("ram_style=\"block\"")]
let _a: logic<10> = 1;
#[sv("mark_debug=\"true\"")]
let _b: logic<10> = 1;
}
allow アトリビュート
allow アトリビュートは指定されたリントチェックを無効化するために使用できます。
module ModuleA {
#[allow(unused_variable)]
let a: logic<10> = 1;
}
指定可能なリント名は以下の通りです。
- unused_variable
- missing_reset_statement
- missing_port
ifdef/ifndef/elsif/else アトリビュート
ifdef と ifndef アトリビュートは定義された値によってコードブロックを有効にするかどうかを制御するために使用することができます。さらに、ifdef と ifndef のついたコードブロックに続けてオプションとして elsif と else アトリビュートの付いたブロックを書くこともできます。
以下の例はこれらのアトリビュートの使用方法と、各コードブロックが定義された値によって有効になる様子を示しています。
ifdef/elsif/elseの順に宣言されたアトリビュート- もし
DEFINE_Aが定義されていれば、#[ifdef(DEFINE_A)]のついたコードブロック(コードブロックa)が有効になり、#[ifndef(DEFINE_B)]と#[else]のついたコードブロック(コードブロックbとc)は無効になります。 DEFINE_Aが定義されておらず、DEFINE_Bが定義されていれば、#[elfif(DEFINE_B)]のついたコードブロック(コードブロックb)が有効になり、#[ifndef(DEFINE_A)]と#[else]のついたコードブロック(コードブロックaとc)は無効になります。DEFINE_AとDEFINE_Bが定義されていなければ、#[else]のついたコードブロックが有効になり、#[ifndef(DEFINE_A)]と#[elsif(DEFINE_B)]のついたコードブロック(コードブロックaとb)は無効になります。
- もし
ifndef/elseの順に宣言されたアトリビュート- もし
DEFINE_Dが定義されていなければ、#[ifndef(DEFINE_D)]のついたコードブロック(コードブロックd)が有効になり、#[else]のついたコードブロック(コードブロックe)は無効になります。 DEFINE_Dが定義されていれば、#[else]のついたコードブロック(コードブロックe)が有効になり、#[ifndef(DEFINE_D)]のついたコードブロック(コードブロックd)は無効になります。
- もし
module ModuleA {
#[ifdef(DEFINE_A)]
{
// コードブロック a
let _a: logic<10> = 1;
}
#[elsif(DEFINE_B)]
{
// コードブロック b
let _a: logic<10> = 2;
}
#[else]
{
// コードブロック c
let _a: logic<10> = 3;
}
#[ifndef(DEFINE_D)]
{
// コードブロック d
let _b: logic<10> = 4;
}
#[else]
{
// コードブロック e
let _b: logic<10> = 5;
}
}
生成されたコードにおける末尾カンマ周りの複雑な調整を回避するため、カンマ区切りリストの最後のアイテムにifdefをつけることは禁止されています。
expand アトリビュート
expand アトリビュートが設定されているとき、modport のような構造化されたポートはVerilog のポートに展開されます。合成ツールによってはトップモジュールがそのようなポートを含んではならない場合があり、そのような場合にこのアトリビュートを使うことができます。使用可能な引数は以下の通りです。
modport: ポート方向がmodportのポートを展開する
interface InterfaceA::<W: u32> {
var ready: logic ;
var valid: logic ;
var data : logic<W>;
modport master {
ready: input ,
valid: output,
data : output,
}
modport slave {
ready: output,
valid: input ,
data : input ,
}
}
#[expand(modport)]
module ModuleA (
slave_if : modport InterfaceA::<8>::slave [4],
master_if: modport InterfaceA::<8>::master [4],
) {
for i in 0..4 :g {
connect slave_if[i] <> master_if[i];
}
}
module ModuleB {
inst a_if: InterfaceA::<8> [4];
inst b_if: InterfaceA::<8> [4];
inst u: ModuleA (
slave_if : a_if,
master_if: b_if,
);
}
align アトリビュート
align アトリビュートはフォーマッタの垂直方向の整列を制御することができます。number が align の引数として指定されたとき、全ての数値は整列されます。identifier も使用可能です。
module ModuleA {
let a : logic<32> = 1;
let aa : logic<32> = 1;
let aaa: logic<32> = 1;
let _b: logic = {
a[0] repeat 1, a[0] repeat 1,
aa[1] repeat 8, aa[1] repeat 8,
aaa[2] repeat 16, aaa[2] repeat 16,
};
#[align(number, identifier)]
let _c : logic = {
a [0 ] repeat 1 , a [0 ] repeat 1 ,
aa [1 ] repeat 8 , aa [1 ] repeat 8 ,
aaa[2 ] repeat 16, aaa[2 ] repeat 16,
};
}
fmt アトリビュート
fmt アトリビュートはフォーマットの方法を制御することができます。以下の引数がサポートされています。
compact: 改行なしのコンパクトなフォーマット
module ModuleA {
#[fmt(compact)]
{
inst u1: $sv::Module #( A: 1, B: 2 ) ( x: 1, y: _ );
inst u2: $sv::Module #( A: 1, B: 2 ) ( x: 1, y: _ );
inst u3: $sv::Module #( A: 1, B: 2 ) ( x: 1, y: _ );
inst u4: $sv::Module #( A: 1, B: 2 ) ( x: 1, y: _ );
}
}
skip:veryl fmtはモジュール、インターフェース、パッケージをフォーマットしない