source: soft/giet_vm/applications/gameoflife/main.c @ 697

Last change on this file since 697 was 669, checked in by alain, 9 years ago

Introduce support for the "shared" argument in the giet_tty_alloc() system call,
and replace the giet_shr_printf() system call by giet_tty_printf().

File size: 7.9 KB
RevLine 
[502]1//////////////////////////////////////////////////////////////////////////////////
[509]2// File    : main.c  (for gameoflife)
3// Date    : November 2013 / February 2015
4// Authors :  Alexandre Joannou <alexandre.joannou@lip6.fr> november 2013
5//            Alain Greiner <alain.greiner@lip6.fr> february 2015
[502]6//
[669]7// This multi-threaded application is an emulation of the Game of Life automaton.
[502]8// The world size is defined by the HEIGHT and WIDTH parameters.
[509]9// There is one task per processor.
10// Each task compute HEIGHT/nbprocs lines.
[669]11// Task running on processor P(0,0,0) initialises the barrier, the TTY terminal,
12// and the chained buffer DMA controler.
[509]13//
[502]14// The number of processors must be a power of 2 not larger than HEIGHT.
15//////////////////////////////////////////////////////////////////////////////////
[251]16
17#include "stdio.h"
18#include "limits.h"
[502]19#include "user_barrier.h"
[251]20#include "mapping_info.h"
[669]21#include "hard_config.h"
[251]22
23#define WIDTH           128
24#define HEIGHT          128
25#define NB_ITERATION    1000000000
26
[669]27#define PRINTF(...) ({ if ( proc_id==0) { giet_tty_printf(__VA_ARGS__); } })
[251]28
[509]29typedef unsigned char uint8_t;
[251]30
[509]31uint8_t WORLD[2][HEIGHT][WIDTH] __attribute__((aligned(64)));
[295]32
[509]33uint8_t DISPLAY[2][HEIGHT][WIDTH] __attribute__((aligned(64)));
[251]34
[669]35unsigned int status0[16];
36unsigned int status1[16];
37
[509]38giet_sqt_barrier_t barrier;
[251]39
[509]40volatile unsigned int init_ok;
[251]41
[509]42////////////////////////////////////
43void init_world( unsigned int phase,
44                 unsigned int base_line,
45                 unsigned int nb_line )
[251]46{
[509]47   unsigned int x,y;
48   for (y = base_line ; y < base_line + nb_line ; y++)
[502]49   {
[509]50      for(x = 0 ; x < WIDTH ; x++) 
[502]51      {
[509]52         WORLD[phase][y][x] = (giet_rand() >> (x % 8)) & 0x1;
[251]53      }
54   }
55}
56
[509]57//////////////////////////////////////////////////////
58uint8_t number_of_alive_neighbour( unsigned int phase,
59                                   unsigned int x, 
60                                   unsigned int y )
[251]61{
62   uint8_t nb = 0;
63
[509]64   nb += WORLD[phase][(y - 1) % HEIGHT][(x - 1) % WIDTH];
65   nb += WORLD[phase][ y              ][(x - 1) % WIDTH];
66   nb += WORLD[phase][(y + 1) % HEIGHT][(x - 1) % WIDTH];
67   nb += WORLD[phase][(y - 1) % HEIGHT][ x             ];
68   nb += WORLD[phase][(y + 1) % HEIGHT][ x             ];
69   nb += WORLD[phase][(y - 1) % HEIGHT][(x + 1) % WIDTH];
70   nb += WORLD[phase][ y              ][(x + 1) % WIDTH];
71   nb += WORLD[phase][(y + 1) % HEIGHT][(x + 1) % WIDTH];
[251]72
73   return nb;
74}
75
[509]76/////////////////////////////////////////
77uint8_t compute_cell( unsigned int phase,
78                      unsigned int x, 
79                      unsigned int y )
[251]80{
[509]81   uint8_t nb_neighbours_alive = number_of_alive_neighbour( phase, x , y );
82
83   if (WORLD[phase][y][x] == 1) 
[502]84   {
85      if (nb_neighbours_alive == 2 || nb_neighbours_alive == 3)  return 1;
[251]86   }
[502]87   else 
88   {
89      if (nb_neighbours_alive == 3) return 1;
[509]90      else                          return WORLD[phase][y][x];
[251]91   }
92   return 0;
93}
94
[509]95/////////////////////////////////////////
96void compute_new_gen( unsigned int phase,
97                      unsigned int base_line, 
98                      unsigned int nb_line )
[251]99{
[509]100   unsigned int x,y;
[295]101   for (y = base_line; y < base_line + nb_line; y++)
102   {
103      for(x = 0; x < WIDTH ; x++) 
104      {
[509]105         WORLD[phase][y][x] = compute_cell( 1 - phase , x , y ); 
[251]106      }
107   }
108}
109
[509]110////////////////////////////////////
111void copy_world( unsigned int phase,
112                 unsigned int base_line,
113                 unsigned int nb_line )
[251]114{
[509]115   unsigned int x,y;
[502]116   for (y = base_line; y < base_line + nb_line; y++)
117   {
118      for(x = 0; x < WIDTH ; x++) 
119      {
[509]120         DISPLAY[phase][y][x] = WORLD[phase][y][x]*255; 
[251]121      }
122   }
123}
124
[263]125////////////////////////////////////////
[251]126__attribute__((constructor)) void main()
[669]127////////////////////////////////////////
[251]128{
[432]129   // get processor identifier
130   unsigned int x;
131   unsigned int y;
132   unsigned int p;
133   giet_proc_xyp( &x, &y, &p );
134
[502]135   // get processors number
136   unsigned int x_size;
137   unsigned int y_size;
[669]138   unsigned int nprocs;
139   giet_procs_number( &x_size, &y_size, &nprocs );
[502]140
[509]141   // compute continuous processor index & number of procs
[669]142   unsigned int proc_id = (((x * y_size) + y) * nprocs) + p; 
143   unsigned int n_global_procs = x_size * y_size * nprocs; 
[432]144
[509]145   unsigned int i;
[251]146
[509]147   unsigned int nb_line       = HEIGHT / n_global_procs;
148   unsigned int base_line     = nb_line * proc_id; 
[251]149   
[669]150   // parameters checking
151   giet_assert( (n_global_procs <= HEIGHT),
152                " Number or processors larger than world height" );
[251]153
[669]154   giet_assert( ((WIDTH == FBUF_X_SIZE) && (HEIGHT == FBUF_Y_SIZE)),
155                "Frame Buffer size does not fit the world size" );
156   
157   giet_assert( ((x_size == 1) || (x_size == 2) || (x_size == 4) ||
158                 (x_size == 8) || (x_size == 16)),
159                "x_size must be a power of 2 no larger than 16" );
[509]160
[669]161   giet_assert( ((y_size == 1) || (y_size == 2) || (y_size == 4) ||
162                 (y_size == 8) || (y_size == 16)),
163                "y_size must be a power of 2 no larger than 16" );
164
165   giet_assert( ((nprocs == 1) || (nprocs == 2) || (nprocs == 4)), 
166                "nprocs must be a power of 2 no larger than 4" );
167
168   // P[0,0,0] makes initialisation
[295]169   if ( proc_id == 0 )
170   {
[669]171      // get a private TTY for P[0,0,0]
172      giet_tty_alloc( 0 );
173
174      // get a Chained Buffer DMA channel
[509]175      giet_fbf_cma_alloc();
176
[669]177      // initializes the source and destination buffers
178      giet_fbf_cma_init_buf( &DISPLAY[0][0][0] , 
179                             &DISPLAY[1][0][0] , 
180                             status0 ,
181                             status1 );
182
183      // activates CMA channel
184      giet_fbf_cma_start( HEIGHT * WIDTH );
185
186      // initializes distributed heap
187      unsigned int cx;
188      unsigned int cy;
189      for ( cx = 0 ; cx < x_size ; cx++ )
190      {
191         for ( cx = 0 ; cx < x_size ; cx++ )
192         {
193            heap_init( cx , cy );
194         }
195      }
196
[509]197      // initialises barrier
[669]198      sqt_barrier_init( &barrier , x_size , y_size , nprocs );
[509]199
[669]200      PRINTF("\n[GAMEOFLIFE] P[0,0,0] completes initialisation at cycle %d\n"
201             " nprocs = %d / nlines = %d\n", 
202             giet_proctime() , n_global_procs, HEIGHT );
203
[509]204      // activates all other processors
[502]205      init_ok = 1;
[295]206   }
207   else
208   {
[504]209      while ( init_ok == 0 ) asm volatile("nop\n nop\n nop");
[295]210   }
211
[509]212   ///////////// world  initialization ( All processors )
[502]213
[669]214   // All processors initialize WORLD[0]
[509]215   init_world( 0 , base_line , nb_line );
216
217   // copy WORLD[0] to DISPLAY[0]
218   copy_world( 0 , base_line , nb_line );
219
220   // synchronise with other procs
[502]221   sqt_barrier_wait( &barrier );
222
[509]223   // P(0,0,0) displays DISPLAY[0]
224   if ( proc_id == 0 ) giet_fbf_cma_display ( 0 );
225
[669]226   PRINTF("\n[GAMEOFLIFE] starts evolution at cycle %d\n", giet_proctime() );
[251]227   
[509]228   //////////// evolution : 2 steps per iteration
229
230   for (i = 0 ; i < NB_ITERATION ; i++)
[251]231   {
[509]232      // compute WORLD[1] from WORLD[0]
233      compute_new_gen( 1 , base_line , nb_line );
[502]234
[509]235      // copy WORLD[1] to DISPLAY[1]
236      copy_world( 1 , base_line , nb_line );
237
238      // synchronise with other procs
[502]239      sqt_barrier_wait( &barrier );
240
[509]241      // P(0,0,0) displays DISPLAY[1]
242      if ( proc_id == 0 ) giet_fbf_cma_display ( 1 );
243   
[515]244      PRINTF(" - step %d\n", 2*i );
[509]245   
246      // compute WORLD[0] from WORLD[1]
247      compute_new_gen( 0 , base_line , nb_line );
[251]248
[509]249      // copy WORLD[0] to DISPLAY[0]
250      copy_world( 0 , base_line , nb_line );
251
252      // synchronise with other procs
253      sqt_barrier_wait( &barrier );
254
255      // P(0,0,0) displays DISPLAY[0]
256      if ( proc_id == 0 ) giet_fbf_cma_display ( 0 );
257
[515]258      PRINTF(" - step %d\n", 2*i + 1 );
[509]259   } // end main loop
260
[502]261   PRINTF("\n*** End of main at cycle %d ***\n", giet_proctime());
[251]262
[388]263   giet_exit("Completed");
[251]264} // end main()
265
266// Local Variables:
267// tab-width: 3
268// c-basic-offset: 3
269// c-file-offsets:((innamespace . 0)(inline-open . 0))
270// indent-tabs-mode: nil
271// End:
272
273// vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
274
275
276
Note: See TracBrowser for help on using the repository browser.