HOME

動かしてみた

キャッシュの効き目を確認する

<2008/11/28記>
 P0〜P5領域のキャッシュの効き目を実際に確認してみた。
 リンカのセクション指定と変数のマッピングの関係が分かってないとこんがらがるな。
 ま、ポインタで直接やりゃぁ簡単だ。セクション指定なんぞ関係なくなるもんよ。、

 ところでXYメモリーは特別にキャッシュが効くのだ。
 P2領域からのアクセスでもキャッシュが効くのだ。ちゅうか取説を良く読んだら「キャッシュ有効にしてP2(Lバス)からアクセスしろ。キャッシュ有効のままでP0(Iバス)からアクセスしたら、どうなっても知らんへんで」と書いてあったわ。HARD取説 P225

// キャッシュON
void Oj3_CashOn(void)
{
    wrl(CCR1,rdl(CCR1) | BIT00);
}
// キャッシュOFF
void Oj3_CashOff(void)
{
    wrl(CCR1,rdl(CCR1) & ~BIT00);
}
// ↓これは外部変数。こいつはBセクション内にある。外付けのSDRAMね。
// Bセクションを0C00_0000(P0領域)にマッピングしたのでキャッシュが有効である。
char g_buff[0x100000];

void GRg_main(void)
{
    Oj3_CashOn(); // Cashオン時 0.14秒
    //Oj3_CashOff(); // Cashオフ時 5秒
    for (i=0x0;i<0x100000;++i) g_buff[i]=0xaa;

    // 以下の方法ならセクション指定と無関係にキャッシュの効きを確認可能だ
    Oj3_CashOn(); // Cashオン
    p=(uchar*)0x0C000000; // P0領域からアクセス..キャッシュが効く<7秒
    p=(uchar*)0xAC000000; // P2領域からアクセス..キャッシュが効かない<27秒
    for (i=0x0C000000;i<=0x0FFFFFFF;++i) *p++=0x55;



XYメモリーでキャッシュ

 XYメモリーは速度が速いんで、上手く使うととても結構なり。
 XとYに各8kバイトずつと少ないけど、非常に早いと言うのはエエですな。
 なおP2領域からアクセスすること。P2からのアクセスだけど特別扱いでキャッシュが有効なのだ。キャッシュ参照
 ポインタでアクセスする場合はDSPレジスタを使わないけど、shc専用のXYメモリー定義方式ではDSPレジスタを使うんで、忘れずに特権DSPモードに入ること。
 んま、XYメモリーを使うときは黙って特権DSPモードでやることじゃ。ソース

XYメモリーへのアクセス例
p=(uchar*)0xA5007000; // Xメモリー
p=(uchar*)0xA5017000; // Yメモリー
Oj3_CashOn(); // Cashオン<0.0005秒
//Oj3_CashOff(); // Cashオフ<0.18秒
for (i=0x7000;i<0x8fffu;++i) *p++=0x55;

// shc専用のXYメモリー定義方式の場合
float __X x1; // X に格納
float __Y y1; // Y に格納
void Oj3_CashTest3(void)
{
    Oj3_SetSrDsp();  // 特権DSPモードに入る。
    x1=0.5;             // x1は$XBセクションに自動的に配置される
    y1=0.5;             // y1は$YB                  "
}





固定小数点を使ってみた

<2008/11/28記>
 これがまた分からん。
 どうしても例外エラーが出て途中で止まっちゃう。
 何が悪いのか、何が悪いのか・・メモリーアクセスかCPUモードか・・
 は〜〜アセンブラのソースを見てたら分かったなり〜
 固定小数点の演算ライブラリが内部でDSPレジスタを使ってるじゃん!

grg.c (121): for (i=0; i<NUM; i++) result[i]=input[i] + 0.125r;
                000023C0 Oj3_Fixe..EE00    MOV #0,R14 i
                000023C2 Oj3_Fixe..E108    MOV #8,R1
                000023C4 Oj3_Fixe..3E13    CMP/GE R1,R14 i
                000023C6 Oj3_Fixe..8914    BT 000023F2
                000023C8 Oj3_Fixe..D423    MOV.L 00002458,R4
これ →      000023CA Oj3_Fixe..44BA    LDS R4,Y1
                000023CC Oj3_Fixe..D623    MOV.L 0000245C,R6
                000023CE Oj3_Fixe..62E3    MOV R14 i ,R2

 ここで「LDS R4,Y1」がDSPレジスタへのアクセス命令で、「LDS Rn,Y1」はRn → Y1へのデータ転送命令。HARD取説 P150
 またDSPレジスタには、A0,A1,X0,X1,Y0,Y1,M0,M1がある。HARD取説 P98
 ちゅうことで
固定小数点演算は特権DSPモードで行うこと。ソース
 しっかしRISCプロセッサのアセンブラコードは見たくないねぇ(^^;

固定小数点の範囲

 DSP取説 P88 固定小数点の基礎 ここも参照 
 数値範囲は正確には +0.999..から-1.0 である。
 限界値を使うときは #include <fixed.h> してから FIXED_MIN とか FIXED_MAX を使おうね。
 注意:__fixed で -1.0r とすると -0.999969 になるんで、本当の -1.0 が必要なときは -0.5r-0.5r と書く・・黙って FIXED_MIN を使うこっちゃ。

図10 固定小数点の範囲、添字、型変換
範囲定数 添字 printfの型変換
__fixed(16bit) ±1.0 r %r
long __fixed(32bit) ±1.0 R %lr
__accum(32bit) ±256 a %a
long __accum(64bit) ±256 A %la


 16ビットの固定小数点 __fixed のデータ形式って short とまるっきり同じなのな。なかなか気が付かなかった。
 でも、__fixed に short を代入したら、まともな値が出てこない。
 あれれ?特殊なフォーマットなワケ?とか色々勘ぐっちゃって悩んじゃってDUMPしたりしちゃって・・結局、同じだったのだ。
 __fixed と short はコンパイラの解釈が違うってことみたいね。
 下のコードで実験したら分かったのだ。
 そのまま代入せずに、ポインタを使って無理矢理入れちゃえばOK・・強姦です(^^;
 固定小数点の詳細はここのリンクを見るのだ。

// short を代入してみた
void Oj3_FixedFloatTest(void)
{
    char ss[50];
    short sa,*p;
    __fixed fa;
    Oj3_SetSrDsp();        // 特権DSPモードに入る。

    sa=0xe000;             // -0.25
    fa=(__fixed)sa;
    sprintf(ss,"%r",fa);     // ダメ

    p=(short*)&fa;
    *p=sa;
    sprintf(ss,"%r",fa);     // OK
}



XYメモリー上でやってみた

 XYメモリーを使って固定小数点演算をしたのだ。
 これはつまり後でFFT演算をするときのための下準備ちゅうか練習だな。

// Xメモリー使用例
__fixed __X xa,xb,xc;

void Oj3_FixedFloatTest2(void)
{
    char ss[30];
    __fixed q1,q2,q3;
    float ff,ff2,ff3,ff4;

    // Xメモリーを使うんで特権DSPモードじゃないと動かないのだ。
    Oj3_SetSrDsp();

    // fixedのローカル変数はPALMICEでは正常に見えないが結果はOK
    q1=0.2r;
    q2=0.3r;
    q3=q1 * q2;
    sprintf(ss,"%r",q3);

    // 即値の場合は結果が範囲内であればOK
    q1=2.0r / 10.0r;
    sprintf(ss,"%r",q1);

    // -1.0rは使えない、-0.5r-0.5rと記述すること
    q1=-1.0r;
    sprintf(ss,"%r",q1); // 結果は-0.999969となる
    q1=-0.5r-0.5r;
    sprintf(ss,"%r",q1); // 結果は-1.0となる
    q1=FIXED_MIN;     // FIXED_MINが良いよ
    sprintf(ss,"%r",q1); // 結果は-1.0となる

    xa=0.2r;
    xb=0.3r;
    // 固定と即値のかけ算 xc=0.08 OK
    xc=xa * 0.4r;
    sprintf(ss,"%r\n",xc);
    // 固定同士のかけ算 xc=0.06 OK
    xc=xa * xb;
    sprintf(ss,"%r\n",xc);

    ff2=5.0;
    ff3=0.5;
    ff4=3.2;
    // 浮動 ← 固定 ff=0.06 OK
    ff=xc;
    sprintf(ss,"%f\n",ff);

    // 浮動 ← 固定+即値 ff=5.06 OK
    ff=xc + 5.0;
    sprintf(ss,"%f\n",ff);

    // 浮動 ← 浮動+浮動  ff2=5.56OK
    ff2=ff + ff3;
    sprintf(ss,"%f\n",ff2);

    // 浮動 ← 固定+浮動 ff=3.26 OK
    ff=ff4 + xc;
    sprintf(ss,"%f\n",ff);
    nop();
}



飽和演算だと

 DSP取説 P93によると「結果が演算範囲を超えると、強制的に最大値(最小値)に置き換えること」と書いてあるな。
 早速試してみた。

    __fixed a,result;
    __sat __fixed b;
    // ↓これはダメ。aかbを__sat修飾しないと飽和演算にならない。
    //__fixed a,b;
    //__sat __fixed result;
    Oj3_SetSrDsp(); // 特権DSPモードじゃないと動かないよ。

    a=0.8r; b=0.5r; result=a+b;     // 結果は+1.0(+0.999..)になる
    a=-0.8r; b=-0.5r; result=a+b;  // 結果は-1.0になる

HOME