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

Last change on this file since 669 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
Line 
1//////////////////////////////////////////////////////////////////////////////////
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
6//
7// This multi-threaded application is an emulation of the Game of Life automaton.
8// The world size is defined by the HEIGHT and WIDTH parameters.
9// There is one task per processor.
10// Each task compute HEIGHT/nbprocs lines.
11// Task running on processor P(0,0,0) initialises the barrier, the TTY terminal,
12// and the chained buffer DMA controler.
13//
14// The number of processors must be a power of 2 not larger than HEIGHT.
15//////////////////////////////////////////////////////////////////////////////////
16
17#include "stdio.h"
18#include "limits.h"
19#include "user_barrier.h"
20#include "mapping_info.h"
21#include "hard_config.h"
22
23#define WIDTH           128
24#define HEIGHT          128
25#define NB_ITERATION    1000000000
26
27#define PRINTF(...) ({ if ( proc_id==0) { giet_tty_printf(__VA_ARGS__); } })
28
29typedef unsigned char uint8_t;
30
31uint8_t WORLD[2][HEIGHT][WIDTH] __attribute__((aligned(64)));
32
33uint8_t DISPLAY[2][HEIGHT][WIDTH] __attribute__((aligned(64)));
34
35unsigned int status0[16];
36unsigned int status1[16];
37
38giet_sqt_barrier_t barrier;
39
40volatile unsigned int init_ok;
41
42////////////////////////////////////
43void init_world( unsigned int phase,
44                 unsigned int base_line,
45                 unsigned int nb_line )
46{
47   unsigned int x,y;
48   for (y = base_line ; y < base_line + nb_line ; y++)
49   {
50      for(x = 0 ; x < WIDTH ; x++) 
51      {
52         WORLD[phase][y][x] = (giet_rand() >> (x % 8)) & 0x1;
53      }
54   }
55}
56
57//////////////////////////////////////////////////////
58uint8_t number_of_alive_neighbour( unsigned int phase,
59                                   unsigned int x, 
60                                   unsigned int y )
61{
62   uint8_t nb = 0;
63
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];
72
73   return nb;
74}
75
76/////////////////////////////////////////
77uint8_t compute_cell( unsigned int phase,
78                      unsigned int x, 
79                      unsigned int y )
80{
81   uint8_t nb_neighbours_alive = number_of_alive_neighbour( phase, x , y );
82
83   if (WORLD[phase][y][x] == 1) 
84   {
85      if (nb_neighbours_alive == 2 || nb_neighbours_alive == 3)  return 1;
86   }
87   else 
88   {
89      if (nb_neighbours_alive == 3) return 1;
90      else                          return WORLD[phase][y][x];
91   }
92   return 0;
93}
94
95/////////////////////////////////////////
96void compute_new_gen( unsigned int phase,
97                      unsigned int base_line, 
98                      unsigned int nb_line )
99{
100   unsigned int x,y;
101   for (y = base_line; y < base_line + nb_line; y++)
102   {
103      for(x = 0; x < WIDTH ; x++) 
104      {
105         WORLD[phase][y][x] = compute_cell( 1 - phase , x , y ); 
106      }
107   }
108}
109
110////////////////////////////////////
111void copy_world( unsigned int phase,
112                 unsigned int base_line,
113                 unsigned int nb_line )
114{
115   unsigned int x,y;
116   for (y = base_line; y < base_line + nb_line; y++)
117   {
118      for(x = 0; x < WIDTH ; x++) 
119      {
120         DISPLAY[phase][y][x] = WORLD[phase][y][x]*255; 
121      }
122   }
123}
124
125////////////////////////////////////////
126__attribute__((constructor)) void main()
127////////////////////////////////////////
128{
129   // get processor identifier
130   unsigned int x;
131   unsigned int y;
132   unsigned int p;
133   giet_proc_xyp( &x, &y, &p );
134
135   // get processors number
136   unsigned int x_size;
137   unsigned int y_size;
138   unsigned int nprocs;
139   giet_procs_number( &x_size, &y_size, &nprocs );
140
141   // compute continuous processor index & number of procs
142   unsigned int proc_id = (((x * y_size) + y) * nprocs) + p; 
143   unsigned int n_global_procs = x_size * y_size * nprocs; 
144
145   unsigned int i;
146
147   unsigned int nb_line       = HEIGHT / n_global_procs;
148   unsigned int base_line     = nb_line * proc_id; 
149   
150   // parameters checking
151   giet_assert( (n_global_procs <= HEIGHT),
152                " Number or processors larger than world height" );
153
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" );
160
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
169   if ( proc_id == 0 )
170   {
171      // get a private TTY for P[0,0,0]
172      giet_tty_alloc( 0 );
173
174      // get a Chained Buffer DMA channel
175      giet_fbf_cma_alloc();
176
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
197      // initialises barrier
198      sqt_barrier_init( &barrier , x_size , y_size , nprocs );
199
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
204      // activates all other processors
205      init_ok = 1;
206   }
207   else
208   {
209      while ( init_ok == 0 ) asm volatile("nop\n nop\n nop");
210   }
211
212   ///////////// world  initialization ( All processors )
213
214   // All processors initialize WORLD[0]
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
221   sqt_barrier_wait( &barrier );
222
223   // P(0,0,0) displays DISPLAY[0]
224   if ( proc_id == 0 ) giet_fbf_cma_display ( 0 );
225
226   PRINTF("\n[GAMEOFLIFE] starts evolution at cycle %d\n", giet_proctime() );
227   
228   //////////// evolution : 2 steps per iteration
229
230   for (i = 0 ; i < NB_ITERATION ; i++)
231   {
232      // compute WORLD[1] from WORLD[0]
233      compute_new_gen( 1 , base_line , nb_line );
234
235      // copy WORLD[1] to DISPLAY[1]
236      copy_world( 1 , base_line , nb_line );
237
238      // synchronise with other procs
239      sqt_barrier_wait( &barrier );
240
241      // P(0,0,0) displays DISPLAY[1]
242      if ( proc_id == 0 ) giet_fbf_cma_display ( 1 );
243   
244      PRINTF(" - step %d\n", 2*i );
245   
246      // compute WORLD[0] from WORLD[1]
247      compute_new_gen( 0 , base_line , nb_line );
248
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
258      PRINTF(" - step %d\n", 2*i + 1 );
259   } // end main loop
260
261   PRINTF("\n*** End of main at cycle %d ***\n", giet_proctime());
262
263   giet_exit("Completed");
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.