[PIC] ウェイト ループの最適解を求める

Posted by
ぴろり
Posted at
2014/12/30 17:24
Trackbacks
関連記事 (0)
Post Comment
コメントできます
Category
電子工作 カテゴリ
カバーイメージ

 PIC アプリケーションで任意の時間またはプログラム サイクル数のウェイトが必要になった場合、NOP などの無駄な命令を必要なだけループで回して時間を稼ぐ方法があります。動作クロックが 10 MHzであった場合、一段のループで稼げるのは高々 2,000 サイクル 900 μ秒程度です。更に長い時間を稼ぐには、このループを二段、三段と入れ子にする必要がありますが、そうすると、所望するウェイトに対して各ループ段に必要なループ回数を正確に求めることが困難になります*1
 そこで、複数段のループで構成されるウェイト処理について、最適なループ回数を簡単に計算できる Excel シートを作ってみました。所望するウェイト時間またはサイクル数を入力して、Excel のソルバー アドオンで最適解を見つけられます。また、GUI で数値を増減させて、手作業で近似解を求める作業をお手伝いします。

このエントリーをはてなブックマークに追加  

ウェイト用コード

WAIT:
  ;--- LOOP3>>> ---
  movlw   D'86'         ; 1 cycle
  movwf   CNT3          ; 1
LOOP3:
    ;--- LOOP2>>> ---
    movlw   D'86'       ; 1
    movwf   CNT2        ; 1
LOOP2:
      ;--- LOOP1>>> ---
      movlw   D'86'     ; 1
      movwf   CNT1      ; 1
LOOP1:
      <NOP>             ; nop
      decfsz  CNT1, F   ; 1
      goto    LOOP1     ; 2
      <NOP1>            ; nop1
      ;--- <<<LOOP1 ---
    decfsz  CNT2, F     ; 1
    goto    LOOP2       ; 2
    <NOP2>              ; nop2
    ;--- <<<LOOP2 ---
  decfsz  CNT3, F       ; 1
  goto    LOOP3         ; 2
  <NOP3>
  ;--- LOOP3>>> ---

解説

14 行目
 時間を浪費するための無駄処理が入ります。NOP で 1 サイクル、GOTO $+1 で 2 サイクル稼げますが、そもそも稼げる無駄時間が少ないので、これを必要回数だけループで回す必要があります。しかも、このループの終了判定や繰り返し自体にも数サイクルを要するので、無駄命令を増やしてウェイトを稼ぐよりも、ループ回数を増やした方が楽ちんです。そのため、あってもなくても構いません。
 あまり重要でありませんが、それを利用して、もしループ回数の増減だけで所望のウェイトが得られなかった場合、ここでのウェイト数を変えた上で所要ループ回数を計算しなおすと、より良い解を得られる可能性があります。
15~16 行目
 カウンタ(CNTx)を 1 ずつ減じながら、カウンタが 0 になるまで GOTO LOOPxでループを繰り返します。この処理だけでも 3 サイクルを要してしまうので、先述のように場合によっては 14 行目はなくても良いのです。

各ループ段での所要実行サイクル数

LOOP1 の実行サイクル数; LOOP1

\hspace{25}1+1+(nop+1+2)CNT1-1+nop1\\=\:(nop+3)CNT1+nop1+1\\here\:1{\leq}CNT1{\leq}256,\,0{\leq}nop1\,and\,0{\leq}nop

LOOP2 の実行サイクル数; LOOP2

\hspace{25}1+1+(LOOP1+1+2)CNT2-1+nop2\\=\:(LOOP1+3)CNT2+nop2+1\\=\:\{(nop+3)CNT1+nop1+4\}CNT2+nop2+1\\here\:1{\leq}CNT1{\leq}256,\,0{\leq}nop1\,and\,0{\leq}nop\\\:and\:1{\leq}CNT2{\leq}256,\,0{\leq}nop2\

LOOP3 の実行サイクル数; LOOP3

\hspace{25}1+1+(LOOP2+1+2)CNT3-1+nop3\\=\:(LOOP2+3)CNT3+nop3+1\\=\:\[\{(nop+3)CNT1+nop1+4\}CNT2+nop2+4\]CNT3+nop3+1\\here\:1{\leq}CNT1{\leq}256,\,0{\leq}nop1\,and\,0{\leq}nop\\\:and\:1{\leq}CNT2{\leq}256,\,0{\leq}nop2\\\:and\:1{\leq}CNT3{\leq}256,\,0{\leq}nop3

 …とまぁ、こんな感じで上記計算のように、二段目以降になると前段のループ回数が入れ子で乗算に係ってくるため、サイクル数を正確に求めることが難しくなります。

 例えば、2 段のループで 10,000 サイクルのウェイトを構成したい場合、CNT1CNT2 は幾つにすればよいでしょうか? 大ざっぱに計算すると、1 段目のループで 100 サイクル稼いで、これを 2 段目のループで 100 回回せば良さそうなので、これを土台にして、CNT1=33, CNT2=98 を計算すると 10,095 サイクル、CNT1=33, CNT2=97 であれば 9,992 サイクルを求められます。
 大ざっぱなウェイトであればこれで十分ですが、もうちょっと正確に求められないでしょうか? 例えば、1 段目で 50 サイクル稼いだ上で、2 段目のループでこれを 200 回回してみるとか… つまり (1 段目)×(2 段目)=10,000 となるような計算になるのですが、各変数が 0 から 255 の整数値しか取れないという制約があるので、良い答えを見つけるために試行錯誤が必要になるのです。

 ちなみに、後述の計算用シートを用いて求めた値では、CNT1=132, CNT2=2510,001 サイクルを得ることができます。

ウェイト ループ カウンタ計算用シート

使い方

 シート内でイタリック体で書かれている数字はユーザが入力します。

動作クロック周波数 [MHz]
 PIC に供給される動作クロックを入力します。実行サイクル数から実行時間の計算に使用しています。
エンベロープの大きさ [c]
 ウェイト処理をサブ ルーチン コールしたり、前後処理を追加した際に、ウェイト処理以外に要するサイクル数を設定しておくと、目標値からパラメータの最適解を求める際に加味してくれます。
NOP上限
 ウェイト処理に役する命令数の上限を設定します。nop 命令で 1 サイクル、goto $+1で 2 サイクル浪費できます。多くすれば 1 段ループあたりの最大ウェイトを大きくでき、かつソルバー利用で最適解を求められる幅が広がりますが、その分プログラムメモリを消費しますので、微調整目的で。
NOPxCNTx
 数値を直接入力することで、各段の実行サイクル数(LOOPx)と実行時間(Tx)を求められます。また、その下の +/- ボタンを押すと数値を増減できます。
目標値
 LOOPx または Tx に所望する値を入力して、Microsoft Excel の ソルバー アドオンを利用すれば、各段の NOPxCNTx について最適な設定値を計算してくれます。ソルバーの設定内容は、ページ下段のソルバー用設定内容ストアのセル内容を、ソルバー ダイアログから読み込んでから利用してください。

 Microsoft Excel 以外、例えば LibreOffice などのオフィス スートでも、このシートを読み込んで利用できますが、ソルバーを用いて最適解を求めることができません。非線形問題に対応したソルバー エンジンが必要ですが、LibreOffice には線形アルゴリズムのエンジンしか搭載していないためです。*3

いろいろ

  • Microsoft Excel 2010 で動作確認済みです。
  • ソルバーの使い方/設定値が悪いのか、明らかに最適解が求められる場合でも失敗する場合があります。多段ループになるほど失敗している感じ。
  • ライセンスは GPL です。
このエントリーをはてなブックマークに追加  

  1. *1 後述の実行サイクル数の計算式を参照
  2. *2 VBA マクロを含みますが、+/- ボタンでセルの値を増減させるため処理が書かれています
  3. *3 実は最初、 LibreOffice で作り始めたのですが、非線形ソルバーが必要だと判って Excel で作り直したのです

この記事を読んだ人はこんな記事も読んでいます記事リコメンデーションについて

カバー画像:ぬるぬるローションの製作

関連記事/トラックバック

関連記事/トラックバックはまだありません

この記事にトラックバックを送るには?

コメントを投稿する

 
 (必須, 匿名可, 公開, トリップが使えます)
 (必須, 匿名可, 非公開, Gravatar に対応しています)
 (必須)
スパム コメント防止のため「投稿確認」欄に ランダムな数字 CAPTCHAについて を入力してから送信してください。お手数ですがご協力のほど宜しくお願いいたします。