SSブログ

サイクルタイムを測定しよう (11) [FMx]このエントリーを含むはてなブックマーク#

FM0+ 評価ボード

前回は、最小ループのサイクル数を測定しました。 今回は、ループの配置アドレスによってサイクル数に差が出るかについて調べました。

ソースコード

配置アドレスを変更する考え方は、 PSoC で行った方法と同じです。 ループの前に "nop" 命令を追加して、ループのアドレスを移動します。 以下のコードで、 "nop" 命令の数を調整します。

void func9(reg8_t *reg, uint8_t val0, uint8_t val1) @ ".text.func9" {
    __asm(
        "nop\n"     // 29
        "nop\n"     // 28
        "nop\n"     // 27
        "nop\n"     // 26
        "nop\n"     // 25
        "nop\n"     // 24
        "nop\n"     // 23
        "nop\n"     // 22
        "nop\n"     // 21
        "nop\n"     // 20
        "nop\n"     // 19
        "nop\n"     // 18
        "nop\n"     // 17
        "nop\n"     // 16
        "nop\n"     // 15
        "nop\n"     // 14
        "nop\n"     // 13
        "nop\n"     // 12
        "nop\n"     // 11
        "nop\n"     // 10
        "nop\n"     // 9
        "nop\n"     // 8
        "nop\n"     // 7
        "nop\n"     // 6
        "nop\n"     // 5
        "nop\n"     // 4
        "nop\n"     // 3
        "nop\n"     // 2
        "nop\n"     // 1
        "label_1:"
    );
    for (;;) {
        *reg = val0;
        *reg = val1;
    }
}

func9() 関数は、 @ 指示子によって、セクション名が決められています。 このセクション名を "icf" ファイルで指定する事で、 func9() 関数の境界を定めることが出来ます。

define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };
define block FUNC9     with alignment = 32 { section ".text.func9" };
define block MAIN      with alignment = 32 { section ".text.main" };
:
:
place in ROM_region   { readonly, block FUNC9, block MAIN };

このプロジェクトの場合、上記の記述が入っています。 "define block" でブロック名を定義します。 FUNC9 ブロックには ".text.func9" セクションが入っており、 alignment を 32 と定義しています。 この記述により、 func9() 関数は 32 バイト境界に配置されます。

測定結果

サイクル数を測定した所、周期的に4サイクルと6サイクルのパターンを繰り返す事がわかりました。

NOP数サイクル数分岐先アドレス分岐命令
040206
140408
24060A
34080C
440A0E
560C10
660E12
741014
841216
941418
104161A
114181C
1241A1E
1361C20
1461E22
1542024
1642226
1742428
184262A
194282C
2042A2E
2162C30
2262E32
2343034
2443236
2543438
264363A
274383C
2843A3E
2963C40

サイクル数が6サイクルになるのは、分岐先アドレスの下4ビットが 11xx になるときです。 このとき、分岐先のアドレスと分岐命令アドレスの上位部分が異なっているのがわかります。 例えば、 NOP 数が 5 の時、分岐先アドレスの上位4ビットは 0000 ですが、分岐命令アドレスの上位4ビットは 0001 です。 このように、分岐先と分岐命令が16バイト境界を超えるとサイクル数が増えます。

これは、16バイト境界を超えると分岐先命令をフェッチするために追加サイクルが必要になり、サイクル数が伸びたと考えられます。 また、 Flash ROM のフェッチバッファのサイズは16バイトであるとも推測できます。

ひとつだけ腑に落ちない点もあります。 例えば、 NOP数が 4 の時、分岐命令は 0E にあります。 分岐命令が実行される時、命令がプリフェッチされているのであれば、バッファには 10 から 17 までの内容がロードされているはずです。 その場合、分岐先の命令がバッファに入っていないので、当然、再度フェッチが発生し、サイクル数が伸びるはずです。 しかし、実際には、4サイクルのままです。 この事実から推測されるのは、分岐実行の前にプリフェッチが行われていないのか、プリフェッチバッファが多数存在するかのどちらかです。 この測定結果からは、どちらとも言えません。


nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。