プログラムの作成 (LIFEゲーム)


今回はプログラムの一例としてライフゲームを取り上げます。
ライフゲームとは以下のような生物シミュレーションです。
今回作成したVGAコントローラはキャラクタタイプの表示装置ですので、表示 したい箇所のビデオメモリに表示したい文字のキャラクタコードを書き込めばOKで す。
VGAのビデオメモリの先頭アドレスは "xparameters.h" というファイル内に "XPAR_VRAM_0_MEM0_BASEADDR"で定義されています。書き込みたい箇所の座標をX、 Yとするとき、
XPAR_VRAM_0_MEM0_BASEADDR + ( ( Y * 80 ) + X ) * 4 
のアドレスに書き込みます。


プログラミング言語CによるLIFEゲームプログラムは以下のようになります。


ソース コメント
#include <xparameters.h>

#define XSIZ 60
#define YSIZ 20

char what( int , int );
void v_puts( int , int , char * );

static char data1[XSIZ][YSIZ] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
  0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};


main()
{
  char data2[XSIZ][YSIZ];
  int  i,j,num;
  static char *banner = "Microblaze Softcore Processor Video System";
  
  v_puts( 0, 0, banner );
  
  for( j=0; j<16; j++ ){
    for( i=0; i<16 ; i++ ) {
      *( (unsigned char *)XPAR_VGA_0_MEM0_BASEADDR + ((j+9)*80 + (i+64)) * 4 ) = 16*j+i;
    }
  }
  
  
  for( i=0; i<XSIZ; i++ ){
    for( j=0 ; j<YSIZ ; j++ ) {
      data2[i][j] = 0;
    }
  }
  
  while(1) {
    for( i=0; i<XSIZ; i++ ){
      for( j=0 ; j<YSIZ ; j++ ) {
        num=0;
        if( what(i-1,j-1) ) num++;
        if( what(i-1,j  ) ) num++;
        if( what(i-1,j+1) ) num++;
        if( what(i  ,j-1) ) num++;
        if( what(i  ,j+1) ) num++;
        if( what(i+1,j-1) ) num++;
        if( what(i+1,j  ) ) num++;
        if( what(i+1,j+1) ) num++;
        if( what(i,j) ) {
          if( num == 2 || num == 3 )
            data2[i][j]=1;
          else
            data2[i][j]=0;
        } else if( num == 3 ) data2[i][j]=1;
      }
    }
    
    for( i=0; i<XSIZ; i++ ){
      for( j=0 ; j<YSIZ ; j++ ) {
        data1[i][j] = data2[i][j];
        *( (unsigned char *)XPAR_VGA_0_MEM0_BASEADDR + 1600 + (80*j+(XSIZ-i-1))*4 )
             = data2[i][j] ? '@' : ' ';
        data2[i][j] = 0;
      }
    }
    
    for( i=0; i<=256; i++ ){
      for( j=0 ; j<4000 ; j++ ) {
        *( (unsigned char *)XPAR_VGA_0_MEM0_BASEADDR + 319 ) = i;
      }
    }
    
  }
}

char what( int i, int j)
{
  if( i < 0 ) return 0;
  if( j < 0 ) return 0;
  if( i == XSIZ ) return 0;
  if( j == YSIZ ) return 0;
  return data1[i][j];
}

void v_puts( int x, int y, char *str )
{
  char *p, *addr;
  
  addr = (unsigned char *)XPAR_VGA_0_MEM0_BASEADDR + (y*80 + x) * 4;
  for( p=str ; *p!='\0' ; p++, addr+=4 ) {
    *addr = *p;
  }
}







data1[XSIZ][YSIZ] : 生物の初期データ
生物が居るところを 1, 居ない所を 0 としている。
初期データとして、ペンタデカスロン (pentadecathlon) および
グライダーガン (gliderguns) が配置されてある。




























































タイトル文字領域以外の画面の消去





data2 配列の初期化







data1 配列の各要素毎に、周りの8マスの生物の状態を調べて生物の個数をカウ ントする。
中心に生物がいるとき、まわりに2〜3つの生物が居れば、中心 の生物は生き残る。
中心に生物がいないとき、まわりに3つの生物が居れ ば、中心に生物が誕生する。 次世代の状態を data2 配列に作成する。















data2 配列内を data1 配列にコピーするとともに、
画面上に生物の状態を配置する。







256×4000回の時間待ちループ。右上にキャラクタを表示しながらループする。







what( i, j ) : data1 配列内の data1[i][j] の生物の状態を返す関数







v_puts( x, y, string ) : (x,y)座標から string 文字列を画面に表示する。

このプログラムを,XPS内にソフトウェアプロジェクトとして登録します。 以下のように、"Applications" タブの "Add Software Application Project..." の所でマウスの右をクリックすると、"Add Software Application Project..." メニューか表示されるので、これをマウスの左クリックで選択します。



プロジェクト名として "life" を入力し OK を押します。



"Project: life" の前にある □+ をクリックします。下図のように "Sources" の所でマウスの右をクリックし、"Add New Files..." をマウスの左で選択しま す。



"Source/Header File to create and add to Project" ウィンドウの "Create New Folder" アイコンを押してLIFEプロジェクト用の新しいディレクトリを作成 します。



作成した"life"ディレクトリをマウスでダブルクリックしてディレクトリ内に入っ た後、"File Name:" の所に "life.c" と入力して "Save" を押します。



"Sources" の前にある □+ をクリックします。 "/home/ユーザID/life/life/life.c" をダブルクリックすると ウィンドウの右側が "life.c" タブとなり空のファイルが表示されます。 ここに上に記載のプログラムを入力し、保存します。



次に、入力したプログラムをコンパイルして、プロセッサが理解できる形式の ファイルに変換します。"Project: life" 右クリックして選択した後、下図の ように "Mark to Initialize BRAMs"にチェックを入れます。再び、"Project: life" 右クリックして選択した後、"Build Project" をマウスの左で選択しま す。



コンパイル終了後、下記のように "Console" タブに表示されると正常にファイ ルが生成されています。
 make -f life.make life_program started...
mb-gcc -O2 life/life.c  -o life/executable.elf \
    -mxl-soft-mul -mxl-pattern-compare -mcpu=v7.20.a   -g
    -I./microblaze_0/include/  -L./microblaze_0/lib/  \
      
mb-size life/executable.elf 
text   data    bss    dec    hexfilename
2206   1496   1064   4766   129elife/executable.elf
Done!

それでは実際に、 動作確認 を行ってみます。
| Back | Top | Next |