【目次に戻る】

4. KUE-CHIP2のSFL記述


いよいよKUE-CHIP2全体を,SFLのモジュールkuechip2として記述し ます.リスト4.1に一例を示します.

ファイルのインクルード (3行目から6行目) [TOP]

モジュールkuechip2では,これまでに設計したモジュール kueshiftkuealuをサブモジュールとして用います.それ らのSFL記述は,必ずしもここにインクルードする必要はないのですが,イン クルードすると論理合成の際に便利です.%iと空白に続けて ""でファイル名を囲むことで,カレントディレクトリか ら見たパス名のファイルをインクルードします.

図1のブロック図には,INCという8ビット のインクリメンタがあります.8ビットのインクリメンタはまだ設計していな いのですが,PARTHENON標準ライブラリの中にinc8という8ビットの インクリメンタが存在しますので,これを用いることにします.PARTHENON標 準ライブラリは,$PARTHENON/sfl_lib.dirというディレクトリに,多くのファ イルとして格納されていますが,%iと空白に続けて<>でファイル名を囲むことで,このディレクトリにあるファイル をインクルードします.

inc8.cirというファイルの中身は,リスト4.2の ようになっています.inc8は,機能回路として定義されています. 機能回路はモジュールのようなものですが,論理合成されない,使える演算子 と構成要素が拡張されているなどという点でモジュールと異なっています.機 能回路の記述は,circuitで始めます.inc8などの PARTHENON標準ライブラリは,すでに論理合成されてそのネットリストが用意 されていますので,機能回路で定義されているわけです.

インタフェースの宣言 (8行目から24行目) [TOP]

モジュールkuechip2では,これまでに設計したモジュール kueshift, kuealuやPARTHENON標準ライブラリのinc8を, それぞれサブモジュールshifter, alu, incとして用います.そのた めには,インタフェースの宣言が必要ですので,ここで行っています. inc8のインタフェースの宣言は,inc8.hというファイル(リスト4.3)にあります.kueshiftの制御入力 端子doの仮引数と,kuealuの制御入力端子doの 仮引数は,ともに,すべてのデータ入力端子とします.

マクロ定義 (26行目から39行目) [TOP]

SFLでは,%dを用いてマクロ定義を行います.たとえば,NOP という文字列は,(ir<7:3> == 0b00000)という文字列に置き換えられま す. ここではマクロ定義を用いて,表1に 従って命令の分類を行っています.

外部端子の定義 (43行目から48行目) [TOP]

ここからは,モジュールkuechip2の定義部の記述となります.ま ずは,外部端子を記述します.KUE-CHIP2の外部端子はすでに規定されている ので,ここにはそれらを書き下せばよいのですが,どれを制御端子にしてどれ をデータ端子にするかということを決める必要があります.

まず入力端子に関してですが,kuechip2を起動するための startを制御入力端子とし,メモリやIBUFの値を読み込むための dbi<8>,IBUF_FLAG, OBUF_FLAGを読み込むためのibuf_flg_in, obuf_flg_inをデータ入力端子とします.出力端子に関しては,メモリの 値の読み出しを依頼するmem_re,メモリへ値の書き込みを依頼する mem_we,IBUFの値の読み出しを依頼するibuf_re,OBUFへ 値の書き込みを依頼するobuf_weは制御出力端子にします.そして, メモリやOBUFに値を書き込むためのdbo<8>,メモリのアドレスを指 定するためのab<9>はデータ出力端子とします.

構成要素の定義 (51行目から59行目) [TOP]

次はkuechip2の構成要素を記述します.まずレジスタに関しては, 図1に示したように,acc, ix, cf, vf, nf, zf, pc, ir, marを用意します.KUE-CHIP2のレジスタはリセット信 号でリセットされるので,レジスタとしてはreg_wr (register with reset)を用いることにします.そのほかに,図1に示されているものとしては, モジュールkueshift, kuealuを,それぞれサブモジュール shifter, aluとして用い,PARTHENON標準ライブラリのinc8を, サブモジュールincとして用います.また,データ内部端子として, sel_bを用意します.

そのほかに,図1にはありませんが,SFL記述を簡潔にするためのいくつか の構成要素を定義します.bcond_calc, bcond_statusは,BRANCH命 令を処理するために設けた制御内部端子です.exec_aluは, aluを用いて算術論理演算命令を処理するための制御内部端子です. 制御内部端子は,制御入力端子や制御出力端子と同様に,起動されなければそ の値は0で,起動されるとその値が1になります.また,動作を関連づけること もできます.これらの働きについてはもう少し後で説明します.

制御端子の仮引数の定義 (62行目から65行目) [TOP]

制御端子のうち,制御出力端子と制御内部端子の仮引数の定義は,モジュー ルの定義部で行います.制御出力端子と制御内部端子は,これらを持つモジュー ルによって起動されるからです.

mem_reabを仮引数として持つものとします.メモリ の内容を読みだすためには,アドレスを与えなければならないからです. mem_weについては,アドレスだけではなく,メモリに書き込むべき データの値も与えなければならないので,abdboを仮引 数とします.obuf_weについては,書き込むべきデータの値だけを与 えれば良いので,dboを仮引数とします.

exec_alusel_bを仮引数として持つものとします. 図1に示すように,sel_baluの入力の1つとなるからです.

ステージとタスクと仮引数の定義 (68行目) [TOP]

SFLには,ステージという概念があります.制御端子は1クロックで終了す る動作を行うのに対し,ステージは複数クロックにまたがる一連の動作を行い ます. すなわち,ステージは状態を持ちますが,制御端子は状態を持ちませ ん.

ステージを複数個用意すると,並列動作をうまく記述することができます. しかし,ここではステージを一つだけ用意し,その唯一のステージの名前を allとします.ステージallは,表1に示されたフェーズ表に従って,各命令の 動作を制御するものとします.

ステージにはタスクというものが存在し,これが起動されることでステー ジが動作すると考えられています.ステージallにもタスクが必要で す.tという名前のタスクを用意します.

制御端子による動作 (71行目から100行目) [TOP]

次に,制御端子による動作を記述します.制御端子のうち,制御入力端子 と制御内部端子による動作の定義は,これらを持つモジュールの定義部で行わ れます.一方,制御出力端子による動作の定義は,その制御出力端子を持つモ ジュールの外,つまりそのモジュールをサブモジュールとして使用するモジュー ルで行われます.従って,ここでは行われません.

制御入力端子startが起動されると,generateという SFLのキーワードにより,ステージallのタスクtが起動さ れ,KUE-CHIP2が動き出します.

制御内部端子bcond_calcは,命令コードとフラグの値に従って, BRANCH命令の分岐条件を判定します.分岐条件の詳細については,規定課題の 資料を見てください.もし条件が成り立てば,制御内部端子 bcond_statusを起動して1にします.条件が成り立たなければ, bcond_statusは0のままです.

制御内部端子exec_aluは,aluを用いて算術論理演算命 令を行い,フラグを更新します.算術論理演算命令の第1オペランドは, ir<3>が1か0かで,ixaccとなります.命令の 第2オペランドは,exec_aluの仮引数sel_bに与えられた値 となります.演算結果は,ir<3>が1か0かで,ixaccに格納されます(比較命令CMP以外).

ステージの動作 (103行目から199行目) [TOP]

最後に,ステージallの動作を記述します.ステージは generateで起動され,起動された次のクロックから動作を開始し, finishというキーワードで動作を終了します.したがって,ステー ジallは制御入力端子startによって動作を開始し,HLT命 令により動作を終了します.

ステージallは3つの状態を持つものとし,表1に示した3つのフェーズp1, p2, p3をそれぞ れの状態に対応させます.状態p1では,命令の種類によらず動作は一定 ですが,状態p2, p3での動作は命令の種類によって異ってきます.状態 を持つステージでは,どれかの1つの状態のみが有効になっています.ステー ジが動作中であっても,有効でない状態の動作は行われません.初めに有効な 状態(初期状態)は,キーワードfirst_stateで指定します.有効な状 態の変更(状態遷移)は,キーワードgotoによって行います.

表1とこのSFL記述を見比べることで,SFL記述の意味がわか りやすくなると思います.

制御端子の起動 [TOP]

kuechip2のSFL記述には,制御端子の起動がたくさん現れています.制 御端子は,その後に()を付けることで起動します.制御端子は,制御入 力端子,制御出力端子,制御内部端子に分けられますが,ここでは,それぞれ の起動について説明します.

まず,制御入力端子についてですが,サブモジュールの制御入力端子は, これを使用している外側のモジュールが起動します.例えば141行目では,サ ブモジュールshifterの制御入力端子doを,ir<2:0>, ix, cfを引数として起動しています.これにより,kueshiftdoの 仮引数の定義(14行目)に従って,shifterのデータ入力端子mode, in, ciに,それぞれ,ir<2:0>, ix, cfの値が転送されます.ま た,shifterdoが1になり,それに対応づけられた動作が行われ ます.この動作は,モジュールkueshiftの定義部に記述されています. このように,制御入力端子を用いて,あるモジュールからそこで使用している サブモジュールに仕事を依頼します.

次に,制御出力端子について見てみます.例えば107行目では,制御出力端 子mem_reを,0b0 || pcを引数として起動しています.こ れにより,62行目の仮引数の定義に従って,データ出力端子ab0b0 || pcの値が転送されます.また,mem_reが1になり, それに対応づけられた動作が行われます.この動作とは,メモリの ab番地の内容をdbiに転送することですが,これはモジュー ルkuechip2の外側で規定されます.このように,制御出力端子を用 いて,あるモジュールから外側のモジュールに仕事を依頼します.

最後に制御内部端子について見てみます.例えば157行目では, ixを引数として制御内部端子exec_aluを起動しています. これにより,65行目の仮引数の定義に従って,データ内部端子sel_bixの値が転送されます.また,exec_aluが1になり,そ れに対応づけられた動作が行われます.この動作は90行目から100行目に書か れています.制御内部端子は,制御入力端子や制御出力端子のように別のモジュー ルに仕事を依頼するものではなく,一連のまとまった動作を記述するためのも のです.これを用いることでSFL記述を簡潔にすることができます.

以上で,リスト4.1の説明は終わりです.リスト4.1のSFL記述は, kuechip2.sflというファイルに格納するものとします.

リスト4.1: SFL記述 (kuechip2.sfl) [TOP]
  1  /** kuechip2 : The main module of KUE-CHIP2 **/
  2  
  3  %i "kueshift.sfl"
  4  %i "kuealu.sfl"
  5  %i 
  6  %i 
  7  
  8  declare kueshift {
  9      /** external pins **/
 10      instrin     do;
 11      input       mode<3>, in<8>, ci;
 12      output      out<8>, co, vo, no, zo;
 13      /** arguments of instrin **/
 14      instr_arg   do(mode, in, ci);
 15  }
 16  
 17  declare kuealu {
 18      /** external pins **/
 19      instrin     do;
 20      input       mode<3>, a<8>, b<8>, ci;
 21      output      out<8>, co, vo, no, zo;
 22      /** arguments of instrin **/
 23      instr_arg   do(mode, a, b, ci);
 24  }
 25  
 26  %d NOP    (ir<7:3> == 0b00000)
 27  %d HLT    ((ir<7:3> == 0b00001) | (ir<7:4> == 0b0101))
 28  %d OUT    (ir<7:3> == 0b00010)
 29  %d IN     (ir<7:3> == 0b00011)
 30  %d SRCF   (ir<7:4> == 0b0010)
 31  %d BRANCH (ir<7:4> == 0b0011)
 32  %d SHIFT  (ir<7:4> == 0b0100)
 33  %d LD_REG ((ir<7:4> == 0b0110) & (ir<2:1> == 0b00))
 34  %d AL_REG ((ir<7> == 0b1)      & (ir<2:1> == 0b00))
 35  %d LD_IMM ((ir<7:4> == 0b0110) & (ir<2:1> == 0b01))
 36  %d AL_IMM ((ir<7> == 0b1)      & (ir<2:1> == 0b01))
 37  %d LD_MA  ((ir<7:4> == 0b0110) & (ir<2> == 0b1))
 38  %d ST_MA  ((ir<7:4> == 0b0111) & (ir<2> == 0b1))
 39  %d AL_MA  ((ir<7> == 0b1)      & (ir<2> == 0b1))
 40  
 41  module kuechip2 {
 42      /** external pins **/
 43      instrin     start;
 44      input       dbi<8>;
 45      input       ibuf_flg_in, obuf_flg_in;
 46      instrout    mem_we, mem_re;
 47      instrout    ibuf_re, obuf_we;
 48      output      dbo<8>, ab<9>;
 49  
 50      /** elements **/
 51      reg_wr      acc<8>, ix<8>;
 52      reg_wr      cf, vf, nf, zf;
 53      reg_wr      pc<8>, ir<8>, mar<8>;
 54      kuealu      alu;
 55      kueshift    shifter;
 56      inc8        inc;
 57      sel         sel_b<8>;
 58      instrself   bcond_calc, bcond_status;
 59      instrself   exec_alu;
 60  
 61      /** arguments of instrout and instrself **/
 62      instr_arg   mem_re(ab);
 63      instr_arg   mem_we(ab, dbo);
 64      instr_arg   obuf_we(dbo);
 65      instr_arg   exec_alu(sel_b);
 66  
 67      /** stages and tasks and their arguments **/
 68      stage_name  all { task t(); }
 69  
 70      /** operations of instrin and instrself **/
 71      instruct start generate all.t();
 72      instruct bcond_calc if (
 73          ( ir<3:0> == 0b0000 ) |
 74          ( ( ir<3:0> == 0b1000 ) & vf ) |
 75          ( ( ir<3:0> == 0b0001 ) & ^zf ) |
 76          ( ( ir<3:0> == 0b1001 ) & zf ) |
 77          ( ( ir<3:0> == 0b0010 ) & ^nf ) |
 78          ( ( ir<3:0> == 0b1010 ) & nf ) |
 79          ( ( ir<3:0> == 0b0011 ) & ^(nf | zf) ) |
 80          ( ( ir<3:0> == 0b1011 ) & nf | zf ) |
 81          ( ( ir<3:0> == 0b0100 ) & ^ibuf_flg_in ) |
 82          ( ( ir<3:0> == 0b1100 ) & obuf_flg_in ) |
 83          ( ( ir<3:0> == 0b0101 ) & ^cf ) |
 84          ( ( ir<3:0> == 0b1101 ) & cf ) |
 85          ( ( ir<3:0> == 0b0110 ) & ^(vf @ nf) ) |
 86          ( ( ir<3:0> == 0b1110 ) & vf @ nf ) |
 87          ( ( ir<3:0> == 0b0111 ) & ^((vf @ nf) | zf) ) |
 88          ( ( ir<3:0> == 0b1111 ) & (vf @ nf) | zf )
 89                              ) bcond_status();
 90      instruct exec_alu par {
 91          any {
 92              ir<3> : alu.do(ir<6:4>, ix, sel_b, cf);
 93              else : alu.do(ir<6:4>, acc, sel_b, cf);
 94          }
 95          if ( ^(ir<6:4> == 0b111) ) any { /* except CMP */
 96              ir<3> : ix := alu.out;
 97              else : acc := alu.out;
 98          }
 99          cf := alu.co; vf := alu.vo; nf := alu.no; zf := alu.zo;
100      }
101  
102      /** operations of stages **/
103      stage all {
104          state_name p1, p2, p3;
105          first_state p1;
106          state p1 par {
107              ir := mem_re(0b0 || pc).dbi;
108              pc := inc.do(pc).out;
109              goto p2;
110          }
111          state p2 any {
112              NOP : goto p1;
113              HLT : par {
114                  goto p1;
115                  finish;
116              }
117              OUT : par {
118                  obuf_we(acc);
119                  goto p1;
120              }
121              IN : par {
122                  acc := ibuf_re().dbi;
123                  goto p3;
124              }
125              SRCF : par {
126                  cf := ir<3>;
127                  goto p1;
128              }
129              BRANCH : par {
130                  bcond_calc();
131                  mem_re(0b0 || pc);
132                  inc.do(pc);
133                  any {
134                      bcond_status : pc := dbi;
135                      else : pc := inc.out;
136                  }
137                  goto p1;
138              }
139              SHIFT : par {
140                  any {
141                      ir<3> : ix := shifter.do(ir<2:0>, ix, cf).out;
142                      else : acc := shifter.do(ir<2:0>, acc, cf).out;
143                  }
144                  cf := shifter.co; vf := shifter.vo;
145                  nf := shifter.no; zf := shifter.zo;
146                  goto p1;
147              }
148              LD_REG : par {
149                  any {
150                      ir<0> & ^ir<3> : acc := ix;
151                      ^ir<0> & ir<3> : ix := acc;
152                  }
153                  goto p1;
154              }
155              AL_REG : par {
156                  any {
157                      ir<0> : exec_alu(ix);
158                      else : exec_alu(acc);
159                  }
160                  goto p1;
161              }
162              LD_IMM : par {
163                  any {
164                      ir<3> : ix := mem_re(0b0 || pc).dbi;
165                      else : acc := mem_re(0b0 || pc).dbi;
166                  }
167                  pc := inc.do(pc).out;
168                  goto p1;
169              }
170              AL_IMM : par {
171                  exec_alu(mem_re(0b0 || pc).dbi);
172                  pc := inc.do(pc).out;
173                  goto p1;
174              }
175              LD_MA | ST_MA | AL_MA : par {
176                  mem_re(0b0 || pc);
177                  any {
178                      ir<1> : mar := alu.do(0b011, ix, dbi, 0b0).out;
179                      else : mar := dbi;
180                  }
181                  pc := inc.do(pc).out;
182                  goto p3;
183              }
184          }
185          state p3 par {
186              any {
187                  LD_MA : any {
188                      ir<3> : ix := mem_re(ir<0> || mar).dbi;
189                      else : acc := mem_re(ir<0> || mar).dbi;
190                  }
191                  ST_MA : any {
192                      ir<3> : mem_we(ir<0> || mar, ix);
193                      else : mem_we(ir<0> || mar, acc);
194                  }
195                  AL_MA : exec_alu(mem_re(ir<0> || mar).dbi);
196              }
197              goto p1;
198          }
199      }
200  }

リスト4.2: inc8.cir [TOP]
  1  /******************************************
  2  * (C)Copyright by N.T.T 1993(unpublished) *
  3  * All rights are reserved.                *
  4  ******************************************/
  5  circuit inc8 {
  6      input       in<8> ;
  7      output      out<8> ;
  8      instrin     do ;
  9      instruct do out = in + 0b1 ;
 10  }

リスト4.3: inc8.h [TOP]
  1  /******************************************
  2  * (C)Copyright by N.T.T 1993(unpublished) *
  3  * All rights are reserved.                *
  4  ******************************************/
  5  declare inc8 {
  6      input       in<8> ;
  7      output      out<8> ;
  8      instrin     do ;
  9      instr_arg do(in) ;
 10  }