2011年04月17日

AVR互換コア(テスト2)

AVR互換コアのテストも かなり進んだ。もう一息と思っている。今までの状況を一旦まとめてテストの仕上げに入る。

    テストが終われば完成 -- ではない。規模が増えているので Spartan 3A の XC3S50A に入らない。少々の最適化が必要。

まずは、ベースと テストのための AVR_Toolchain について。

  • rtavr-wk09.tar.gz -- AVR互換コア テスト2 の ベースバージョン

    AVR互換コア以外に テスト用のコードと 結果比較のための AVRシミュレータ(simulavr のコアを使用) も含んでいる。

  • AVR_Toolchain-20110409-win.tar.gz -- Windows 版 AVR_Toolchain (27MB ぐらい)
  • AVR_Toolchain-20110409-lin.tar.gz -- Linux 版 AVR_Toolchain (25MB ぐらい)
  • AVR_Toolchain-20110409-src.tar.gz -- AVR_Toolchain パッチ集 (同じものはバイナリにも添付)

    AVR8L 用としては AVR_Toolchain は as5 beta ですら 使い物にならないので、自分で改造した AVR_Toolchain を使う。.. といっても テストがなんとかできるレベル。実用として使うレベルにはなっていないので注意。

    展開すると AVR_Toolchain ディレクトリが出来る。AVR_Toolchain/bin にパスを通せば avr-gcc が使える。展開する場所はどこでも良いし AVR_Toolchain を rename しても良い。AVR Studio 4.18SP3 でも設定することで使用可能。他の MCU にも対応していて Atmel が提供しているものと同レベル。ただしテストしていない。

  • その他のツール

    Verilog シミュレータとして、『Icarus Verilog for Windows』-- Windows 版 setup (GTKWave 同梱) を使っている。Icarus Verilog は 結果を比較するのに必要。GTKWave も使うが結果比較がメインになっていて 補助的になって来ている。

    AVR Studio 4.18SP3 のシミュレータ は attiny40 に対応しているので これも併用。Xiliinx の ISE も Implement のチェックや Verilog の文法チェックに併用している。

avr8l_trace



    AVR互換コアを作ったは良いが、どうやってテストしたものか途方にくれていたのだが...ついに超強力なツールを手に入れることが出来た。それが、これ。

    どういうものかというと AVR のプログラムを実行させて、メモリやレジスタに変化があったときに、フラグやPC, SP と共に そのデータ(+アドレス or レジスタ番号)をログするもの。

    テストベンチの方でも全く同じものを出力するようにしていて、2つのログを取って diff をかければ検証できてしまうのだ。

    もっともテストに使うプログラムは作らないといけない。だが、自分で検証しなくて良いので 書きっぱなしにできるのだ。そして gcc が多少バグっていても問題ない。バグも含めてトレースするから プログラムが必ずしも正しいものである必要はないのだ。

    これを作って一気に気が楽になった。

    ちなみに、これは simulavr-0.1.2.6 のコア decode.c だけを取ってきて、でっち上げたもの。 decode.c の不要な命令は全部削ってしまったので、AVR8L 専用になっている。また、コアだけテストできれば良いので (SREG/SP 以外の)IOレジスタも割り込みもない。

    使い方は、ROM ファイルとして Verilog 用データの rom_data.mem を読み込んで実行させる。終了条件は、実行命令数 と SLEEP 命令。-- 割り込みがないので SLEEP 命令が来たら終了。

    AVR互換コアのテストベンチもほぼ同じ。ただし、実行命令数 をカウントしていないので、クロック数で代替している。

いままでのテストの内容



    shuffle という テストプログラム を作成して、実行させ avr8l_trace を使って 結果を比較してバグを潰してきた。

    shuffle は 16 バイトのデータを 入力して 16 バイトのデータを 出力する一方向関数。MD5 とか 乱数に近いものだが、いろんな命令を使うようにしている。

    テスト専用として作っているので、一方向関数としては不完全。また適当に作ったのでテストとしても不完全。もともとは、出力データを比較することで検証しようとしていたのだが、avr8l_trace の完成でそれは不要になった。なにより gcc のバグ(だと思う)で、最後まで動かずどこかで無限ループしている。

      独自拡張の ldd/std 命令を使っているのを忘れていた。これじゃ avrtiny40 のシミュレータでは動かない。でも、avr8l_trace で 25万命令実行しても shuffle() から戻ってこない。... やっぱり avr-gcc のバグか。

    このテストで 沢山バグを潰すことができた。今や 3000 命令近い実行で結果が一致している。

    その先、一致しないところがあるのだが、ずっと動かした先を調べるのが億劫になって来ている。どういう所がバグっていそうか分かってきたので、今度は 弱点を攻める短いテストプログラムで検証していこうと考えている。

見つかったバグの整理



どういうバグがあったのか整理しておく。これから出るバグも似た様なものになりそうだ。あと、未解決のものがある。

  • フラグの結果不正

    LDI で Z flag を変化させた。
    ANDI/ORI で C flag を変化させた。
    MOV で (複数) flag を変化させた。
    COM で V flag を変化させなかった。

    CP/CPC/SUB/SBC/SUBI での H flag/V flag の間違い
    CPC/SBC/SBCI での Z flag の間違い

    フラグの変更ルールというものを知らなかった。沢山バグが出たのも当然か。

    特に H flag/V flag の計算式が add 系と sub 系で違うのを知らなかったので、2 度引っかかった。あと、Z flag は sub 系のキャリー付きだけ 動作が違うのも。

  • 命令デコードの不正

    RET + PUSH と並んでいるときの SP値 不正
    RCALL + SKIP命令と並んでいるとき call先の1命令が実行されない。
    CBI/SBI で 関係ないレジスタを書き換える。
    LDD/STD デコード 不完全
    CALL でのスタック積み順 (HI byte → LOW byte が正しいが逆だった)

    RET + PUSH や RCALL + SKIP命令は、命令デコードの無効化が完全でなかったのが原因。CBI/SBI と LDD/STD は デコードそのものが 不完全。スタック積み順 はデータシートで見つけられなかったので、どちらか分からなかった。

  • ラッチ関係

    C_in に ラッチが必要だった。( ROR で結果不正 )
    Z_in も不安なのでラッチ (バグが見つかったわけではない)

    上記の 2 系統のバグは想定内だが、これは気がつかなかった。
    C_in などは、IOレジスタなので CLK の 1/2 ( posedge ) で変更する。が、レジスタに取り込むのは、これより後 ( CLK の 3/4 ) だから C_in が変更されてしまい それを元に計算するようなところの値も変わってしまう。Z_in は計算には使わないので問題ない。蛇足だった。

  • SKIP 命令の設計ミス(未修正)

    SKIP 命令はちょっとマズイ。バグは分かっているが、対処方法を決めかねている。

    追記: どうするかは、『AVR互換コア(設計メモ)』の記事に書いた。


テスト t_skip

    最初のテストプログラムは次のようにした。


    uint8_t t_skip(uint8_t a, uint8_t *p) {
    if (a & 1) *p++ = a;
    *p = 0;
    return a & 1;
    }

    main 側:
    t_skip(0xff, buf);
    t_skip(0x00, buf);
    sleep();

    オブジェクト:
    0000007e <t_skip>:
    3f: 2fe6 mov r30, r22
    40: 2ff7 mov r31, r23
    41: fd80 sbrc r24, 0
    42: 9381 st Z+, r24
    43: 8330 st Z, r19
    44: 7081 andi r24, 0x01 ; 1
    45: 9508 ret


    skip 命令の後に POSTINC ... 上記バグにヒットするコード。ちゃんと C だけで作ることが出来た。
    ちなみに、r19 は zero_reg 。(自製 AVR_Toolchain の AVR8L のときの 独自仕様)

    で、このコードは まだ 09 では動かない。設計ミスに対処してなんとか動かすことが出来た。

    -S mem[0060] = 00 : PC 0043 FLAGS 00 SP 0139
    +S mem[0060] = 00 : PC 0042 FLAGS 00 SP 0139

    だが diff で引っかかる。PC は S2 の時点ではもう覚えていない。テストベンチでは、2 クロック前 -- S0 だったはずの時の 値を出力しているのだがパイプラインストールが起きるとずれる。

    この不一致は、パイプラインストールが起きた目印ということにして許容しよう。直すの面倒だし。

    あと別のバグが見つかった。

    SLEEP 命令のとき RET/RETI 命令だと誤認されて RET/RETI の処理も動いてしまった。またもや デコードが甘かった。


    あと cpse も同じように確認したい。

    uint8_t t_skip2(uint8_t a, uint8_t b, uint8_t *p) {
    if (a != b) *p++ = a;
    *p = 0;
    return a & 1;
    }

    000000cc <t_skip2>:
    66: 93df push r29
    67: 93cf push r28
    68: b7cd in r28, 0x3d ; 61
    69: b7de in r29, 0x3e ; 62
    6a: 2fe4 mov r30, r20
    6b: 2ff5 mov r31, r21
    6c: 1386 cpse r24, r22
    6d: 9381 st Z+, r24
    6e: 8330 st Z, r19
    6f: 7081 andi r24, 0x01 ; 1
    70: 91cf pop r28
    71: 91df pop r29
    72: 9508 ret

    cpse は Rd/Rr の不一致でスキップ。avr-gcc もやるなぁ。ちゃんと想定どおりに使ってくる。ちなみに push/pop は フレームポインタ Y の処理。結果として不要だったわけだが、まぁ -Os ではこうなるのかも。

    ところで tb_shuffle での残り問題。


    -L r18 = 01 : PC 0260 FLAGS a1 SP 0124
    +L r18 = 01 : PC 0260 FLAGS a3 SP 0124

    -L r24 = 00 : PC 017a FLAGS 83 SP 0126
    +L r24 = 00 : PC 017a FLAGS 82 SP 0126

    260: 2322 and r18, r18

    17a: 2b84 or r24, r20

    AND/OR で Z flag が違う。

    これも フラグの計算の問題。AND/OR/EOR は H Flag と C Flag だけ変更しない。

    これを修正したところ shuffle は 5000 命令クリア。大分安定してきた。shuffle はまだちゃんと動かないので N-queen を試したところクリア。

    ここで 規模を調べてみたところ 50A 用の rtavr_defs.v で 701 スライス。... 711 からなぜか減った。

09A



  • rtavr-wk09a.tar.gz

    09A 版 スナップショット。

    これでほぼ完成か? いろいろ整理して Ver 1 にしたい。

    ただ、その前にフラグ計算を 整理しておきたい。それで規模が減るなら 採用して余裕を確保しておきたいのだ。第一、今のは美しくない。S1 の段階で 減算と 加算 あとキャリー付き減算をまとめておく。
    この分解能の情報があれば、V/H/Z の処理を大分まとめられる。

    S2 になってから 組み合わせ回路でまとめても論理はかわらないと思うので S1 に持って行ってみる。

      これをやってみたのだが、707 スライスと 却って増えた。ただ、こうやってまとめた先に 単一 ALU化がある。 単一 と言わないまでも OP1/OP2 の加減算を 1 つに出来れば規模は減るはず。エンバグしたかどうかの検証も楽になったし。演算までまとめてみてから判断しようと思う。

09B



  • rtavr-wk09b.tar.gz

    OP3/OP2 の 処理を 1つの ALU にまとめるという ALU 化をやってみたところ 707スライスが、679 スライスまで減った。


      Number of Slice Flip Flops 391
      Number of 4 input LUTs 1,088
      Number of occupied Slices 679
      Total Number of 4 input LUTs 1,124
      Number used as logic 1,072
      Number used as a route-thru 37
      Number used for Dual Port RAMs 16
      Number of bonded IOBs 11
      Number of BUFGMUXs 2
      Number of RAMB16BWEs 3

      ちなみに C Flag を ALU の 9bit 目から 独立させて H Flag と同じ処理にしてみたところ 691 まで増えてしまった。逆に ALU を 2 分割して H Flag を取り出してやると もっと 減るのかも。

      .. これ実際にやってみると 701 と増える。なかなか難しいものだ。

      09B は、ALU_8BIT , ALU_4BITX2 の 2 つの オプションをいれた。これは 整理したときに消してしまうつもりで 今だけのオプションになりそうだ。

    とりあえず、変更したら tb_shuffle/tb_queen/tbi_001 でチェックしているが OK 。tbi_001 は 随時追加している。

    若干の余裕もできたし、ひとまずの完成としよう。これを元に ソースコードも整理する。ifdef のネストがひどいことになっているので、固定化した ifdef は 整理してしまう。

      完成とは書いたが、これがスタート地点でもある。ようやく チューニングしたり いろいろいじるベースが出来たのだ。いじってみて結果を比較することで確認するから、動くバージョンが 1 つあるのはすごく重要。

      avr8l_trace もあるが、結果が違うことはわかっても詳細は分からない。動く rtavr があれば、Verilog シミュレータで内部状態の違いまで比較することが出来る。

      ここから、大胆な変更とかもやりはじめることができるのだ。( ALU 化 もかなり大胆に変更している。)

      あと、やっておきたいのは、SLEEP 命令か。割り込み使うのなら欲しい場合もありそうだ。ただ、使わなくとも プログラムは書けるから オプション。

      もちろん他にやりたいこともある。それは Version 1.0 入れないが、SLEEP だけは別ということ。 SLEEP 命令がないと、機能として不完全という気がするのだ。

    sleep の実装

    実際に作ってみたところ、簡単だった。スリープ状態 r_sleep をひとつ作り、

    r_sleep <= (~s1_invalid & f_sleep) | (r_sleep & ~v_int);

    こんな風に制御する。f_sleep は S1 でのデコード。無効にされてなかったら、次のクロックからスリープ状態。
    v_int は、割り込みが受け付けられたことを示す。要するに割り込みで状態解除。

    ただし、 (~s1_invalid & f_sleep) のときに 割り込みが受け付けられると、割り込み開始と同時にスリープ状態になってしまうので、割り込みを 1 クロック遅らせる。

    あと、 (~s1_invalid & f_sleep | r_sleep ) のときは、パイプラインストールさせる。

    パイプラインストールさせると ROM のアドレスも更新されず同じ状態がずっと続く。クロックを止めたりはしないが、状態が変わらないので消費電流の低減に多少は寄与するはず。

    これだけ入れてどれぐらい規模が増えるか見てみたら 1 スライスだけだった。


    Number of Slice Flip Flops 391 392
    Number of 4 input LUTs 1,088 1,090
    Number of occupied Slices 679 680
    Total Number of 4 input LUTs 1,124 1,126
    Number used as logic 1,072 1,074
    Number used as a route-thru 37
    Number used for Dual Port RAMs 16
    Number of bonded IOBs 11
    Number of BUFGMUXs 2
    Number of RAMB16BWEs 3

    FF 1 個と LUT2 個。でちょうど 1 スライス -- うまいこと入ったものだ。

    1 スライスだけならオプションにするまでもない。標準として入れよう。



    テストは、tb_int0 を使った。int0 を起こす SBI をしてから 実際の割り込みが起きるのは 2 クロック後なので sleep 命令を入れられる。

    これは、ちょうど sleep と割り込みが同時に起きたケースで、割り込みが 1 クロック待たせられている。ところで sei + sleep で間に割り込みを入れてはいけないというルールがあるが、sei が S2 のとき sleep が S1 なので 特別な処理をしなくともこのルールは守られる。... というかもともと、S1 実行中の命令がない状態にしてから 割り込みを起こすので、問題ないようになっていたのだった。



    これは、tb_int0 の最後。だれも 割り込みを起こさないのでこの状態がずっと続く。

実はまだまだだった。

    N-queen が動いたと書いたが、ミスで tbi_001 (の古いバージョン)を動かしていただけだった。... やってみたら N-queen も shuffle と同じく終わらない。

    で、フラグ値が違う問題が 1 つ。

    ( L r16 = 7f )

    L r29 = 01 : PC 00e1 FLAGS 00 SP 0129
    L r17 = ff : PC 00e2 FLAGS 15 SP 0129
    -L r16 = 81 : PC 00e3 FLAGS 35 SP 0129
    +L r16 = 81 : PC 00e3 FLAGS 15 SP 0129

    e1: 50d0 subi r29, 0x00 ; 0
    e2: 9510 com r17
    e3: 9501 neg r16


    NEG の H Flag の計算は特別処理になっているが、計算式が違っていた。

    さらに ... tbi_001 での違い .. パイプラインストールでずれているだけかと思ったら

    L r30 = 64 : PC 00db FLAGS 02 SP 0135
    L r31 = 00 : PC 00dc FLAGS 02 SP 0135
    -S mem[0064] = 00 : PC 00df FLAGS 02 SP 0135
    +S mem[0064] = 01 : PC 00de FLAGS 02 SP 0135
    L r24 = 01 : PC 00e0 FLAGS 00 SP 0135

    dd: 1386 cpse r24, r22
    de: 9381 st Z+, r24
    df: 8330 st Z, r19
    e0: 7081 andi r24, 0x01 ; 1

    書いている値が違う。1 回しか メモリに書いていないから 0xde はスキップされて 0xdf の st で書いていることになる。

    r19 は __zero_reg__ なのだが だれも変更していない。 にもかかわらず 0x01 を書いている。

    ... 原因が分かった。表示通り 0xde を実行して 0xdf をスキップしていたのだった。

    2 クロック目ではなく 3 クロック目をスキップするコードになっていた。これを直すことで、tbi_001 は完全に一致した。

    あとは、shuffle と N-queen を動かすことか。使いたいのは gcc なわけで、結局は動かないままでは先に行けない。

    ちょっと tb_queen を見てみる。DEPATH が 3 までなら最後まで行くようだ。

     
    実行命令数(avr8l_trace)
    DEPATH = 1 97
    DEPATH = 2 680
    DEPATH = 3 1845


    それは良いとして、DEPATH = 3 で結果比較すると 違いが出る。


    rtavr:
    163 L r29 = 01 : PC 00a8 FLAGS 21 SP 0129
    164 L r20 = 00 : PC 00a9 FLAGS 21 SP 0129
    165 L r21 = 00 : PC 00aa FLAGS 21 SP 0129
    166 L r28 = 29 : PC 00ab FLAGS 20 SP 0129
    167 L r29 = 01 : PC 00ac FLAGS 00 SP 0129

    168 L r16 = fe : PC 00da FLAGS 35 SP 0129
    169 L r17 = ff : PC 00db FLAGS 35 SP 0129
    170 L r28 = 2a : PC 00dc FLAGS 21 SP 0129
    171 L r29 = 01 : PC 00dd FLAGS 21 SP 0129

    avr8l_trace:
    163 L r29 = 01 : PC 00a8 FLAGS 21 SP 0129
    164 L r20 = 00 : PC 00a9 FLAGS 21 SP 0129
    165 L r21 = 00 : PC 00aa FLAGS 21 SP 0129
    166 L r28 = 29 : PC 00ab FLAGS 20 SP 0129
    167 L r29 = 01 : PC 00ac FLAGS 00 SP 0129

    168 S mem[0129] = b1 : PC 00b0 FLAGS 35 SP 0128
    169 S mem[0128] = 00 : PC 00b1 FLAGS 35 SP 0127
    170 L r28 = 2c : PC 00b1 FLAGS 21 SP 0127
    171 L r29 = 01 : PC 00b2 FLAGS 21 SP 0127

    a8: 4fdf sbci r29, 0xFF ; 255
    a9: 9149 ld r20, Y+
    aa: 8158 ld r21, Y
    ab: 50cc subi r28, 0x0C ; 12
    ac: 50d0 subi r29, 0x00 ; 0
    ad: 3042 cpi r20, 0x02 ; 2
    ae: 0753 cpc r21, r19
    af: f554 brge .+84 ; 0x1b4 <__stack+0x75>
    b0: d000 rcall .+0 ; 0x162 <__stack+0x23>
    b1: 5fcd subi r28, 0xFD ; 253


    da: 9500 com r16
    db: 9510 com r17
    dc: 5fcf subi r28, 0xFF ; 255
    dd: 4fdf sbci r29, 0xFF ; 255

    0x1b4 にはプログラムはない。一体どこに 分岐するつもりなのか?... と思ったら 逆アセンブラのバグ。分岐先は 0xda 。結局 brge が分岐すかしないかの違い。brge は BRBC 4 と等価で 直前の cpc の S Flag が間違っていることになる。そして正しいフラグ値は 0x35 で S=1 。rtavr は次の命令で変更されているから ログでは分からない。



    これ見ると F554 でのフラグ値は 0x35 で正しい。S も 1 。だがセレクタを通した FLAGS_BIT_IN が 0 。

    wire v_flags_bit = (FLAGS_BIT == 0) ? C_out
    : (FLAGS_BIT == 1) ? Z_out
    : (FLAGS_BIT == 2) ? N_out
    : (FLAGS_BIT == 3) ? S_out
    : (FLAGS_BIT == 4) ? V_out
    : (FLAGS_BIT == 5) ? H_out
    : (FLAGS_BIT == 6) ? T_out
    : I_in ;

    ... なんと S と V が逆だった。これを直すことで DEPATH = 3 の結果が一致した。しかし ... いろいろあるものだ。

    もともと フラグに関しては それらしいコードを埋めるのがやっとだったから、まぁバグが多いのは仕方ない。

    これで最後だと良いのだが...

09C



  • rtavr-wk09c.tar.gz

    09C で 上記のバグを全部直した。あと ifdef も削りだしている。


    09B 09C
    Number of Slice Flip Flops 391 391
    Number of 4 input LUTs 1,088 1,096
    Number of occupied Slices 679 683
    Total Number of 4 input LUTs 1,124 1,132
    Number used as logic 1,072 1,080
    Number used as a route-thru 37 36
    Number used for Dual Port RAMs 16
    Number of bonded IOBs 11
    Number of BUFGMUXs 2
    Number of RAMB16BWEs 3


    少しだが規模は増えた。

    さて、とりあえず用意したテストプログラムは一致するようになった。今度は avr8l_trace でも動かない tb_queen と tb_shuffle を動かす作業に入る。

    その目的で avr8l_trace には SLEEP で レジスタとメモリをダンプする機能を付けた。ところどころ sleep を入れながら avr-gcc をデバッグしていくつもり。

    ちょっとやってみた。

    shuffle() が retuen したら sleep() するようにして、suffle() の中の最後でも sleep()
    これはちゃんと止まるが、suffle() の中のsleep() を nop() にすると止まらない。


    main 側
    5b: d058 rcall .+176 ; 0x168 <shuffle>
    ...
    60: 9588 sleep
    61: 894b ldd r20, Y+19 ; 0x13

    shuffle 側
    00000168 <shuffle>:
    b4: 930f push r16
    b5: 931f push r17
    b6: 93df push r29
    b7: 93cf push r28
    b8: b7cd in r28, 0x3d ; 61
    b9: b7de in r29, 0x3e ; 62
    ba: 51ca subi r28, 0x1A ; 26
    bb: 40d0 sbci r29, 0x00 ; 0
    bc: b72f in r18, 0x3f ; 63
    bd: 94f8 cli
    be: bfde out 0x3e, r29 ; 62
    bf: bf2f out 0x3f, r18 ; 63
    c0: bfcd out 0x3d, r28 ; 61
    c1: 2fe8 mov r30, r24
    c2: 2ff9 mov r31, r25

    :
    :
    238: f731 brne .-52 ; 0x43e <shuffle+0x2d6>
    239: 9588 sleep
    23a: 5ec6 subi r28, 0xE6 ; 230
    23b: 4fdf sbci r29, 0xFF ; 255
    23c: b72f in r18, 0x3f ; 63
    23d: 94f8 cli
    23e: bfde out 0x3e, r29 ; 62
    23f: bf2f out 0x3f, r18 ; 63
    240: bfcd out 0x3d, r28 ; 61
    241: 91cf pop r28
    242: 91df pop r29
    243: 911f pop r17
    244: 910f pop r16
    245: 9508 ret

    結果
    S mem[0126] = 5c : PC 005b FLAGS 80 SP 0125
    S mem[0125] = 00 : PC 005c FLAGS 80 SP 0124
    S mem[0124] = 01 : PC 00b4 FLAGS 80 SP 0123
    S mem[0123] = 27 : PC 00b5 FLAGS 80 SP 0122
    S mem[0122] = 01 : PC 00b6 FLAGS 80 SP 0121
    S mem[0121] = 26 : PC 00b7 FLAGS 80 SP 0120
    L r28 = 20 : PC 00b8 FLAGS 80 SP 0120
    L r29 = 01 : PC 00b9 FLAGS 80 SP 0120
    L r28 = 06 : PC 00ba FLAGS a0 SP 0120
    L r29 = 01 : PC 00bb FLAGS 80 SP 0120
    L r18 = 80 : PC 00bc FLAGS 80 SP 0120
    L r30 = 27 : PC 00c1 FLAGS 80 SP 0106
    L r31 = 01 : PC 00c2 FLAGS 80 SP 0106
         :
    :
    S mem[0134] = 62 : PC 0233 FLAGS 80 SP 0106
    S mem[0135] = 25 : PC 0234 FLAGS 80 SP 0106
    SLEEP : PC 0239 FLAGS 82 SP 0106
    *** inst-count 1999 ***
    *** gpr dump ***
    r16:17 r17:01 r18:00 r19:00 r20:62 r21:25 r22:36 r23:01
    r24:62 r25:25 r26:36 r27:01 r28:06 r29:01 r30:17 r31:01
    *** ram dump ***
    *
    0060: 05 00 01 00 00 00 01 00 01 00 00 00 00 00 00 00
    0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    *
    0100: 00 00 00 02 61 01 a1 9a f5 a6 4f 10 3c 5b f2 62
    0110: 25 62 25 62 25 62 25 08 00 17 01 42 81 26 01 26
    0120: 01 26 01 27 01 00 c6 b7 27 6d 1c 78 cc 55 5b 85
    0130: 62 25 62 25 62 25 42 81 00 00 3f 01 00 00 00 2b
    ****************


    sleep でのレジスタ・メモリが取れているから これをじっくり見ればどこが悪いか分かるはず。
    あと、shuffle の結果もメモリ中にある。

    138c2ff005f01fae0e780ef64dcc849b
    2 1 2 1 2 0 0 0

    これが PC で取った正しい結果。... 全然合っていないような。..

    下が それぞれの case を通った回数。メモリをみると 5 1 0 1 1 0 0 0 だったと分かる。... 合わないのも当然か。スタックの 戻りアドレス も壊れている。これじゃだめだ。


    L r29 = 01 : PC 0230 FLAGS 80 SP 0106
    L r24 = c6 : PC 0231 FLAGS 94 SP 0106
    L r25 = b7 : PC 0232 FLAGS 94 SP 0106
    S mem[0126] = c6 : PC 0233 FLAGS 94 SP 0106
    S mem[0127] = b7 : PC 0234 FLAGS 94 SP 0106

    22f: 51c3 subi r28, 0x13 ; 19
    230: 40d0 sbci r29, 0x00 ; 0
    231: 2784 eor r24, r20
    232: 2795 eor r25, r21
    233: 938d st X+, r24
    234: 939d st X+, r25

    壊しているのはここ。... となると X がおかしい

    逆に追っていくと、関数の頭のほう Z(r31,r30) が 0127 になっているのが元。

      思うに avr-gcc のコード生成で、アセンブラ(相当)を出力するのコードのなかのどれかで、X/Y/Z レジスタ を間違えているものがあるんじゃないだろうか?

      avr-gcc の AVR8L 対応のコードは ベースと 1:1 に対応するコードしか生成していない。機械的な変換だから こういう単純なバグしか入らないはず。

      そういう観点で一回チェックしてみよう。

(続く)
関連記事:

著作権について

    ここで提示しているコードは正しく動作しないとはいえ、既に著作権は発生しています。
    著作権は、すzが保持しており放棄はしていません。

    教育目的および私用目的では、もともと著作権の範囲外なので自由につかえます。また、ライセンスとして、GPL を適用しています。GPL に従う範囲において 個別の許可なく使用することができます。許諾のための連絡も不要です。

    なお、GPL なので、生成したバイナリを作り直せる範囲のソース開示が必要になります。FPGA だと 通常 チップ全体になってしまいます。また、開示したソースを GPL の範囲で再利用されることを妨げることはできなくなります。このコードを利用する場合この点に留意してください。

    個別の許可を得れば、GPL 以外の条件での使用は可能です。が、作業中のものには許可は出さない予定です。作業が完了(もしくは中断)したとき、ライセンスは見直します。

    なお、すでに公開してしまったものの、ライセンスを取り消すことはできないと考えていますが、ライセンスの追加は可能です。また、新しく公開するものについては、ライセンスしないことすら可能で、どのような制限もありません。変更する可能性がありますので、この点にも留意してください。
posted by すz at 22:47| Comment(0) | TrackBack(0) | AVR_CORE
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/44406073
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック