SSブログ

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

実験回路

今回は、分岐命令の実行サイクルタイムを測定します。

分岐命令を入れる

前回の記事で、 "nop" 命令を入れた所に "b" 命令を入れます。

    uint32  s;
    uint32  e;
    
    s = *reg;
    asm(
        "b label_2\n"
        "label_2:\n"
    );
    e = *reg;

分岐先は、 "label_2" ラベルで指示します。 まずは、次の命令に分岐した場合について調べます。

このプログラムをコンパイルすると、このようなコードが生成されます。

  39:.\main.c      ****     uint32  s;
  40:.\main.c      ****     uint32  e;
  41:.\main.c      ****     
  59:.\main.c      ****     s = *reg;
  95 0000 0268     		ldr	r2, [r0]
  60:.\main.c      ****     asm(
  99 0002 FFE7     		b label_2
 100              	label_2:
  61:.\main.c      ****         "b label_2\n"
  72:.\main.c      ****         "label_2:\n"
  73:.\main.c      ****     );
  74:.\main.c      ****     e = *reg;
 105 0004 0368     		ldr	r3, [r0]

次の命令に分岐するという事は、動作としては "nop" と変わりありません。 ところが、サイクルタイムは7サイクルと表示されました。

Freq:48
0007 0007 0007 0007 0007 0007 0007 0007
0007 0007 0007 0007 0007 0007 0007 0007

Freq:24
0007 0007 0007 0007 0007 0007 0007 0007
0007 0007 0007 0007 0007 0007 0007 0007

Freq:12
0007 0007 0007 0007 0007 0007 0007 0007
0007 0007 0007 0007 0007 0007 0007 0007

つまり、分岐命令に要したのは、3サイクルという計算になります。 この結果から、分岐命令の処理に3サイクル必要だと判断できます。

命令の配置アドレスを変えてみた

ところが、いかなる場合でも3サイクルになったわけではありませんでした。 分岐命令の配置アドレスによって、サイクルタイムが変わってきたのです。

  39:.\main.c      ****     uint32  s;
  40:.\main.c      ****     uint32  e;
  41:.\main.c      ****     
  42:.\main.c      ****     asm(
  90 0000 C046     		nop
  91 0002 C046     	nop
  92 0004 C046     	nop
  93 0006 C046     	nop
  94              	label_1:
  95              	
  53:.\main.c      ****         "nop\n"   // 4
  54:.\main.c      ****         "nop\n"   // 3
  55:.\main.c      ****         "nop\n"   // 2
  56:.\main.c      ****         "nop\n"   // 1
  57:.\main.c      ****         "label_1:\n"
  58:.\main.c      ****     );
  59:.\main.c      ****     s = *reg;
  99 0008 0268     		ldr	r2, [r0]
  60:.\main.c      ****     asm(
 103 000a FFE7     		b label_2
 104              	label_2:
 105              	
  61:.\main.c      ****         "b label_2\n"
  72:.\main.c      ****         "label_2:\n"
  73:.\main.c      ****     );
  74:.\main.c      ****     e = *reg;
 109 000c 0368     		ldr	r3, [r0]

例えば、このプログラムでは、先頭に "nop" 命令を4個挿入して、コードの位置を8バイト後ろにずらしました。 すると、以下のように表示されました。

Freq:48
0009 0009 0009 0009 0009 0009 0009 0009
0009 0009 0009 0009 0009 0009 0009 0009

Freq:24
0008 0008 0008 0008 0008 0008 0008 0008
0008 0008 0008 0008 0008 0008 0008 0008

Freq:12
0007 0007 0007 0007 0007 0007 0007 0007
0007 0007 0007 0007 0007 0007 0007 0007

このようにバス周波数によってサイクル数が異なっている原因は、 Flash ROM のウェイトサイクルが影響しているものと推測されます。 挿入する "nop" 命令の数を変えながらサイクル数を測定したのが、以下の表です。

NOP数サイクル数
48/24/12
分岐先アドレス
07/7/70004
17/7/70006
27/7/70008
37/7/7000A
49/8/7000C
59/8/7000E
67/7/70010
77/7/70012
89/8/70014
99/8/70016
107/7/70018
117/7/7001A
129/8/7001C
139/8/7001E
147/7/70020

このように NOP 命令が4個(8バイト)増えるごとにサイクルタイムの長いパターンが発生します。 この結果から、プリフェッチバッファは、8バイトで構成されているらしいことが推測されます。 さらに分岐先アドレスに着目すると、飛び先アドレスの LSB 部分が X1X0 であった場合に限りサイクルタイムが長くなっている事がわかります。 これは、8バイトバッファの後半に分岐した場合には、次の8バイトのプリフェッチが追加されているものと推測されます。

今回の実験で、分岐命令の分岐先のアドレスにより、必要なサイクル数が異なってくるらしい事がわかってきました。 実験で見えてきた違いは、1サイクルまたは2サイクルです。 このくらいだったら気にすることも無いですかね。


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

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

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

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