| [708] | 1 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2 | // File   : convol.c | 
|---|
|  | 3 | // Date   : june 2014 | 
|---|
|  | 4 | // author : Alain Greiner | 
|---|
|  | 5 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 6 | // This multi-threaded application implements a 2D convolution product. | 
|---|
|  | 7 | // It can run on a multi-processors, multi-clusters architecture, with one thread | 
|---|
|  | 8 | // per processor, and uses the POSIX threads API. | 
|---|
|  | 9 | // | 
|---|
|  | 10 | // The main() function can be launched on any processor P[x,y,l]. | 
|---|
|  | 11 | // It makes the initialisations, launch (N-1) threads to run the execute() function | 
|---|
|  | 12 | // on the (N-1) other processors than P[x,y,l], call himself the execute() function, | 
|---|
|  | 13 | // and finally call the instrument() function to display instrumentation results | 
|---|
|  | 14 | // when the parallel execution is completed. | 
|---|
|  | 15 | // | 
|---|
|  | 16 | // The convolution kernel is [201]*[35] pixels, but it can be factored in two | 
|---|
|  | 17 | // independant line and column convolution products. | 
|---|
|  | 18 | // The five buffers containing the image are distributed in clusters. | 
|---|
|  | 19 | // | 
|---|
|  | 20 | // The (1024 * 1024) pixels image is read from a file (2 bytes per pixel). | 
|---|
|  | 21 | // | 
|---|
|  | 22 | // - number of clusters containing processors must be power of 2 no larger than 256. | 
|---|
|  | 23 | // - number of processors per cluster must be power of 2 no larger than 8. | 
|---|
|  | 24 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 25 |  | 
|---|
|  | 26 | #include "stdio.h" | 
|---|
|  | 27 | #include "stdlib.h" | 
|---|
|  | 28 | #include "user_barrier.h" | 
|---|
|  | 29 | #include "malloc.h" | 
|---|
|  | 30 |  | 
|---|
|  | 31 | #define USE_SQT_BARRIER            1 | 
|---|
|  | 32 | #define VERBOSE                    1 | 
|---|
|  | 33 | #define SUPER_VERBOSE              0 | 
|---|
|  | 34 |  | 
|---|
|  | 35 | #define X_SIZE_MAX                 16 | 
|---|
|  | 36 | #define Y_SIZE_MAX                 16 | 
|---|
|  | 37 | #define PROCS_MAX                  8 | 
|---|
|  | 38 | #define CLUSTERS_MAX               (X_SIZE_MAX * Y_SIZE_MAX) | 
|---|
|  | 39 |  | 
|---|
|  | 40 | #define INITIAL_DISPLAY_ENABLE     0 | 
|---|
|  | 41 | #define FINAL_DISPLAY_ENABLE       1 | 
|---|
|  | 42 |  | 
|---|
|  | 43 | #define PIXEL_SIZE                 2 | 
|---|
|  | 44 | #define NL                         1024 | 
|---|
|  | 45 | #define NP                         1024 | 
|---|
|  | 46 | #define NB_PIXELS                  (NP * NL) | 
|---|
|  | 47 | #define FRAME_SIZE                 (NB_PIXELS * PIXEL_SIZE) | 
|---|
|  | 48 |  | 
|---|
|  | 49 | #define SEEK_SET                   0 | 
|---|
|  | 50 |  | 
|---|
|  | 51 | #define TA(c,l,p)  (A[c][((NP) * (l)) + (p)]) | 
|---|
|  | 52 | #define TB(c,p,l)  (B[c][((NL) * (p)) + (l)]) | 
|---|
|  | 53 | #define TC(c,l,p)  (C[c][((NP) * (l)) + (p)]) | 
|---|
|  | 54 | #define TD(c,l,p)  (D[c][((NP) * (l)) + (p)]) | 
|---|
|  | 55 | #define TZ(c,l,p)  (Z[c][((NP) * (l)) + (p)]) | 
|---|
|  | 56 |  | 
|---|
|  | 57 | #define max(x,y) ((x) > (y) ? (x) : (y)) | 
|---|
|  | 58 | #define min(x,y) ((x) < (y) ? (x) : (y)) | 
|---|
|  | 59 |  | 
|---|
|  | 60 | // macro to use a shared TTY | 
|---|
|  | 61 | #define printf(...);  { lock_acquire( &tty_lock ); \ | 
|---|
|  | 62 | giet_tty_printf(__VA_ARGS__);  \ | 
|---|
|  | 63 | lock_release( &tty_lock ); } | 
|---|
|  | 64 |  | 
|---|
|  | 65 | ////////////////////////////////////////////////////////// | 
|---|
|  | 66 | //   global variables stored in seg_data in cluster[0,0] | 
|---|
|  | 67 | ////////////////////////////////////////////////////////// | 
|---|
|  | 68 |  | 
|---|
|  | 69 | // Instrumentation counters (cluster_id, lpid] | 
|---|
|  | 70 |  | 
|---|
|  | 71 | unsigned int START[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 72 | unsigned int H_BEG[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 73 | unsigned int H_END[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 74 | unsigned int V_BEG[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 75 | unsigned int V_END[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 76 | unsigned int D_BEG[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 77 | unsigned int D_END[CLUSTERS_MAX][PROCS_MAX]; | 
|---|
|  | 78 |  | 
|---|
|  | 79 | // global synchronization barrier | 
|---|
|  | 80 |  | 
|---|
|  | 81 | #if USE_SQT_BARRIER | 
|---|
|  | 82 | giet_sqt_barrier_t  barrier; | 
|---|
|  | 83 | #else | 
|---|
|  | 84 | giet_barrier_t      barrier; | 
|---|
|  | 85 | #endif | 
|---|
|  | 86 |  | 
|---|
|  | 87 | volatile unsigned int barrier_init_ok    = 0; | 
|---|
|  | 88 | volatile unsigned int load_image_ok      = 0; | 
|---|
|  | 89 | volatile unsigned int instrumentation_ok = 0; | 
|---|
|  | 90 |  | 
|---|
|  | 91 | // lock protecting access to shared TTY | 
|---|
|  | 92 | user_lock_t         tty_lock; | 
|---|
|  | 93 |  | 
|---|
|  | 94 | // global pointers on distributed buffers in all clusters | 
|---|
|  | 95 | unsigned short * GA[CLUSTERS_MAX]; | 
|---|
|  | 96 | int *            GB[CLUSTERS_MAX]; | 
|---|
|  | 97 | int *            GC[CLUSTERS_MAX]; | 
|---|
|  | 98 | int *            GD[CLUSTERS_MAX]; | 
|---|
|  | 99 | unsigned char *  GZ[CLUSTERS_MAX]; | 
|---|
|  | 100 |  | 
|---|
|  | 101 |  | 
|---|
|  | 102 |  | 
|---|
|  | 103 | //////////////////////////////////////////// | 
|---|
|  | 104 | __attribute__ ((constructor)) void execute() | 
|---|
|  | 105 | //////////////////////////////////////////// | 
|---|
|  | 106 | { | 
|---|
|  | 107 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 108 | // Each thread[x,y,p] initialises the convolution kernel parameters in local stack. | 
|---|
|  | 109 | // The values defined in the next 12 lines are Philips proprietary information. | 
|---|
|  | 110 | ///////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 111 |  | 
|---|
|  | 112 | int   vnorm  = 115; | 
|---|
|  | 113 | int   vf[35] = { 1, 1, 2, 2, 2, | 
|---|
|  | 114 | 2, 3, 3, 3, 4, | 
|---|
|  | 115 | 4, 4, 4, 5, 5, | 
|---|
|  | 116 | 5, 5, 5, 5, 5, | 
|---|
|  | 117 | 5, 5, 4, 4, 4, | 
|---|
|  | 118 | 4, 3, 3, 3, 2, | 
|---|
|  | 119 | 2, 2, 2, 1, 1 }; | 
|---|
|  | 120 |  | 
|---|
|  | 121 | int hrange = 100; | 
|---|
|  | 122 | int hnorm  = 201; | 
|---|
|  | 123 |  | 
|---|
|  | 124 | // get plat-form parameters | 
|---|
|  | 125 | unsigned int x_size;             // number of clusters in a row | 
|---|
|  | 126 | unsigned int y_size;             // number of clusters in a column | 
|---|
|  | 127 | unsigned int nprocs;             // number of processors per cluster | 
|---|
|  | 128 | giet_procs_number( &x_size , &y_size , &nprocs ); | 
|---|
|  | 129 |  | 
|---|
|  | 130 | // get processor identifiers | 
|---|
|  | 131 | unsigned int x;                  // x coordinate | 
|---|
|  | 132 | unsigned int y;                  // y coordinate | 
|---|
|  | 133 | unsigned int lpid;               // local proc index | 
|---|
|  | 134 | giet_proc_xyp( &x, &y, &lpid ); | 
|---|
|  | 135 |  | 
|---|
|  | 136 | // indexes for loops | 
|---|
|  | 137 | int c; // cluster index | 
|---|
|  | 138 | int l; // line index | 
|---|
|  | 139 | int p; // pixel index | 
|---|
|  | 140 | int z; // vertical filter index | 
|---|
|  | 141 |  | 
|---|
|  | 142 | int          file       = 0;                            // file descriptor | 
|---|
|  | 143 | unsigned int nclusters  = x_size * y_size;              // number of clusters | 
|---|
|  | 144 | unsigned int cluster_id = (x * y_size) + y;             // continuous cluster index | 
|---|
|  | 145 | unsigned int thread_id  = (cluster_id * nprocs) + lpid; // continuous thread index | 
|---|
|  | 146 | unsigned int nthreads   = nclusters * nprocs;           // number of threads | 
|---|
|  | 147 | unsigned int frame_size = FRAME_SIZE;                   // total size (bytes) | 
|---|
|  | 148 | unsigned int lines_per_thread   = NL / nthreads;        // lines per thread | 
|---|
|  | 149 | unsigned int lines_per_cluster  = NL / nclusters;       // lines per cluster | 
|---|
|  | 150 | unsigned int pixels_per_thread  = NP / nthreads;        // columns per thread | 
|---|
|  | 151 | unsigned int pixels_per_cluster = NP / nclusters;       // columns per cluster | 
|---|
|  | 152 |  | 
|---|
|  | 153 | int first, last; | 
|---|
|  | 154 |  | 
|---|
|  | 155 | unsigned int date = giet_proctime(); | 
|---|
|  | 156 | START[cluster_id][lpid] = date; | 
|---|
|  | 157 |  | 
|---|
|  | 158 | ///////////////////////////////////////////////////////////////////// | 
|---|
|  | 159 | // Each thread[x][y][0] allocate the global buffers in cluster(x,y) | 
|---|
|  | 160 | ///////////////////////////////////////////////////////////////////// | 
|---|
|  | 161 | if ( lpid == 0 ) | 
|---|
|  | 162 | { | 
|---|
|  | 163 |  | 
|---|
|  | 164 | #if VERBOSE | 
|---|
|  | 165 | printf( "\n[CONVOL] thread[%d,%d,%d] enters malloc at cycle %d\n", | 
|---|
|  | 166 | x,y,lpid, date ); | 
|---|
|  | 167 | #endif | 
|---|
|  | 168 |  | 
|---|
|  | 169 | GA[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)   , x , y ); | 
|---|
|  | 170 | GB[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y ); | 
|---|
|  | 171 | GC[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y ); | 
|---|
|  | 172 | GD[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y ); | 
|---|
|  | 173 | GZ[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)/2 , x , y ); | 
|---|
|  | 174 |  | 
|---|
|  | 175 | #if VERBOSE | 
|---|
|  | 176 | printf( "\n[CONVOL]  Shared Buffer Virtual Addresses in cluster(%d,%d)\n" | 
|---|
|  | 177 | "### GA = %x\n" | 
|---|
|  | 178 | "### GB = %x\n" | 
|---|
|  | 179 | "### GC = %x\n" | 
|---|
|  | 180 | "### GD = %x\n" | 
|---|
|  | 181 | "### GZ = %x\n", | 
|---|
|  | 182 | x, y, | 
|---|
|  | 183 | GA[cluster_id], | 
|---|
|  | 184 | GB[cluster_id], | 
|---|
|  | 185 | GC[cluster_id], | 
|---|
|  | 186 | GD[cluster_id], | 
|---|
|  | 187 | GZ[cluster_id] ); | 
|---|
|  | 188 | #endif | 
|---|
|  | 189 | } | 
|---|
|  | 190 |  | 
|---|
|  | 191 | /////////////////////////////// | 
|---|
|  | 192 | #if USE_SQT_BARRIER | 
|---|
|  | 193 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 194 | #else | 
|---|
|  | 195 | barrier_wait( &barrier ); | 
|---|
|  | 196 | #endif | 
|---|
|  | 197 |  | 
|---|
|  | 198 | ////////////////////////////////////////////////////////////////////// | 
|---|
|  | 199 | // Each thread[x,y,p] initialise in its private stack a copy of the | 
|---|
|  | 200 | // arrays of pointers on the shared, distributed buffers. | 
|---|
|  | 201 | ////////////////////////////////////////////////////////////////////// | 
|---|
|  | 202 |  | 
|---|
|  | 203 | unsigned short * A[CLUSTERS_MAX]; | 
|---|
|  | 204 | int            * B[CLUSTERS_MAX]; | 
|---|
|  | 205 | int            * C[CLUSTERS_MAX]; | 
|---|
|  | 206 | int            * D[CLUSTERS_MAX]; | 
|---|
|  | 207 | unsigned char  * Z[CLUSTERS_MAX]; | 
|---|
|  | 208 |  | 
|---|
|  | 209 | for (c = 0; c < nclusters; c++) | 
|---|
|  | 210 | { | 
|---|
|  | 211 | A[c] = GA[c]; | 
|---|
|  | 212 | B[c] = GB[c]; | 
|---|
|  | 213 | C[c] = GC[c]; | 
|---|
|  | 214 | D[c] = GD[c]; | 
|---|
|  | 215 | Z[c] = GZ[c]; | 
|---|
|  | 216 | } | 
|---|
|  | 217 |  | 
|---|
|  | 218 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 219 | // Ech thread[x,y,0] open the file containing image, and load it from disk | 
|---|
|  | 220 | // to the local A[c] buffer (frame_size / nclusters loaded in each cluster). | 
|---|
|  | 221 | // Other threads are waiting on the init_ok condition. | 
|---|
|  | 222 | //////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 223 | if ( lpid==0 ) | 
|---|
|  | 224 | { | 
|---|
|  | 225 | // open file | 
|---|
|  | 226 | file = giet_fat_open( "/misc/philips_1024.raw" , 0 ); | 
|---|
|  | 227 | if (file < 0 ) | 
|---|
|  | 228 | { | 
|---|
|  | 229 | printf("\n[CONVOL ERROR] thread[%d,%d,%d] " | 
|---|
|  | 230 | "cannot open file /misc/philips_1024.raw", | 
|---|
|  | 231 | x, y, lpid ); | 
|---|
|  | 232 | giet_pthread_exit( NULL ); | 
|---|
|  | 233 | } | 
|---|
|  | 234 |  | 
|---|
|  | 235 | #if VERBOSE | 
|---|
|  | 236 | printf( "\n[CONVOL] thread[%d,%d,%d] open file /misc/philips_1024.raw at cycle %d\n", | 
|---|
|  | 237 | x, y, lpid, giet_proctime() ); | 
|---|
|  | 238 | #endif | 
|---|
|  | 239 |  | 
|---|
|  | 240 | unsigned int offset = (frame_size/nclusters)*cluster_id; | 
|---|
|  | 241 | unsigned int size   = frame_size/nclusters; | 
|---|
|  | 242 |  | 
|---|
|  | 243 | if ( giet_fat_lseek( file, | 
|---|
|  | 244 | offset, | 
|---|
|  | 245 | SEEK_SET ) ) | 
|---|
|  | 246 | { | 
|---|
|  | 247 | printf("\n[CONVOL ERROR] thread[%d,%d,%d] " | 
|---|
|  | 248 | "cannot seek file /misc/philips_1024.raw", | 
|---|
|  | 249 | x, y, lpid ); | 
|---|
|  | 250 | giet_pthread_exit( NULL ); | 
|---|
|  | 251 | } | 
|---|
|  | 252 |  | 
|---|
|  | 253 | if ( giet_fat_read( file, | 
|---|
|  | 254 | A[cluster_id], | 
|---|
|  | 255 | size ) != size ) | 
|---|
|  | 256 | { | 
|---|
|  | 257 | printf("\n[CONVOL ERROR] thread[%d,%d,%d] " | 
|---|
|  | 258 | "cannot read file /misc/philips_1024.raw", | 
|---|
|  | 259 | x, y, lpid ); | 
|---|
|  | 260 | giet_pthread_exit( NULL ); | 
|---|
|  | 261 | } | 
|---|
|  | 262 |  | 
|---|
|  | 263 | #if VERBOSE | 
|---|
|  | 264 | printf( "\n[CONVOL] thread[%d,%d,%d] load file /misc/philips_1024.raw at cycle %d\n", | 
|---|
|  | 265 | x, y, lpid, giet_proctime() ); | 
|---|
|  | 266 | #endif | 
|---|
|  | 267 |  | 
|---|
|  | 268 | } | 
|---|
|  | 269 |  | 
|---|
|  | 270 | /////////////////////////////// | 
|---|
|  | 271 | #if USE_SQT_BARRIER | 
|---|
|  | 272 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 273 | #else | 
|---|
|  | 274 | barrier_wait( &barrier ); | 
|---|
|  | 275 | #endif | 
|---|
|  | 276 |  | 
|---|
|  | 277 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 278 | // Optionnal parallel display of the initial image stored in A[c] buffers. | 
|---|
|  | 279 | // Eah thread[x,y,p] displays (NL/nthreads) lines. (one byte per pixel). | 
|---|
|  | 280 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 281 |  | 
|---|
|  | 282 | if ( INITIAL_DISPLAY_ENABLE ) | 
|---|
|  | 283 | { | 
|---|
|  | 284 |  | 
|---|
|  | 285 | #if VERBOSE | 
|---|
|  | 286 | printf( "\n[CONVOL] thread[%d,%d,%d] starts initial display at cycle %d\n", | 
|---|
|  | 287 | x, y, lpid, giet_proctime() ); | 
|---|
|  | 288 | #endif | 
|---|
|  | 289 |  | 
|---|
|  | 290 | unsigned int line; | 
|---|
|  | 291 | unsigned int offset = lines_per_thread * lpid; | 
|---|
|  | 292 |  | 
|---|
|  | 293 | for ( l = 0 ; l < lines_per_thread ; l++ ) | 
|---|
|  | 294 | { | 
|---|
|  | 295 | line = offset + l; | 
|---|
|  | 296 |  | 
|---|
|  | 297 | for ( p = 0 ; p < NP ; p++ ) | 
|---|
|  | 298 | { | 
|---|
|  | 299 | TZ(cluster_id, line, p) = (unsigned char)(TA(cluster_id, line, p) >> 8); | 
|---|
|  | 300 | } | 
|---|
|  | 301 |  | 
|---|
|  | 302 | giet_fbf_sync_write( NP*(l + (thread_id * lines_per_thread) ), | 
|---|
|  | 303 | &TZ(cluster_id, line, 0), | 
|---|
|  | 304 | NP); | 
|---|
|  | 305 | } | 
|---|
|  | 306 |  | 
|---|
|  | 307 | #if VERBOSE | 
|---|
|  | 308 | printf( "\n[CONVOL] thread[%d,%d,%d] completes initial display at cycle %d\n", | 
|---|
|  | 309 | x, y, lpid, giet_proctime() ); | 
|---|
|  | 310 | #endif | 
|---|
|  | 311 |  | 
|---|
|  | 312 | //////////////////////////// | 
|---|
|  | 313 | #if USE_SQT_BARRIER | 
|---|
|  | 314 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 315 | #else | 
|---|
|  | 316 | barrier_wait( &barrier ); | 
|---|
|  | 317 | #endif | 
|---|
|  | 318 |  | 
|---|
|  | 319 | } | 
|---|
|  | 320 |  | 
|---|
|  | 321 | //////////////////////////////////////////////////////// | 
|---|
|  | 322 | // parallel horizontal filter : | 
|---|
|  | 323 | // B <= transpose(FH(A)) | 
|---|
|  | 324 | // D <= A - FH(A) | 
|---|
|  | 325 | // Each thread computes (NL/nthreads) lines | 
|---|
|  | 326 | // The image must be extended : | 
|---|
|  | 327 | // if (z<0)    TA(cluster_id,l,z) == TA(cluster_id,l,0) | 
|---|
|  | 328 | // if (z>NP-1) TA(cluster_id,l,z) == TA(cluster_id,l,NP-1) | 
|---|
|  | 329 | //////////////////////////////////////////////////////// | 
|---|
|  | 330 |  | 
|---|
|  | 331 | date  = giet_proctime(); | 
|---|
|  | 332 | H_BEG[cluster_id][lpid] = date; | 
|---|
|  | 333 |  | 
|---|
|  | 334 | #if VERBOSE | 
|---|
|  | 335 | printf( "\n[CONVOL] thread[%d,%d,%d] starts horizontal filter" | 
|---|
|  | 336 | " at cycle %d\n", | 
|---|
|  | 337 | x, y, lpid, date ); | 
|---|
|  | 338 | #else | 
|---|
|  | 339 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 340 | printf( "\n[CONVOL] thread[0,0,0] starts horizontal filter" | 
|---|
|  | 341 | " at cycle %d\n", date ); | 
|---|
|  | 342 | #endif | 
|---|
|  | 343 |  | 
|---|
|  | 344 | // l = absolute line index / p = absolute pixel index | 
|---|
|  | 345 | // first & last define which lines are handled by a given thread | 
|---|
|  | 346 |  | 
|---|
|  | 347 | first = thread_id * lines_per_thread; | 
|---|
|  | 348 | last  = first + lines_per_thread; | 
|---|
|  | 349 |  | 
|---|
|  | 350 | for (l = first; l < last; l++) | 
|---|
|  | 351 | { | 
|---|
|  | 352 | // src_c and src_l are the cluster index and the line index for A & D | 
|---|
|  | 353 | int src_c = l / lines_per_cluster; | 
|---|
|  | 354 | int src_l = l % lines_per_cluster; | 
|---|
|  | 355 |  | 
|---|
|  | 356 | // We use the specific values of the horizontal ep-filter for optimisation: | 
|---|
|  | 357 | // sum(p) = sum(p-1) + TA[p+hrange] - TA[p-hrange-1] | 
|---|
|  | 358 | // To minimize the number of tests, the loop on pixels is split in three domains | 
|---|
|  | 359 |  | 
|---|
|  | 360 | int sum_p = (hrange + 2) * TA(src_c, src_l, 0); | 
|---|
|  | 361 | for (z = 1; z < hrange; z++) | 
|---|
|  | 362 | { | 
|---|
|  | 363 | sum_p = sum_p + TA(src_c, src_l, z); | 
|---|
|  | 364 | } | 
|---|
|  | 365 |  | 
|---|
|  | 366 | // first domain : from 0 to hrange | 
|---|
|  | 367 | for (p = 0; p < hrange + 1; p++) | 
|---|
|  | 368 | { | 
|---|
|  | 369 | // dst_c and dst_p are the cluster index and the pixel index for B | 
|---|
|  | 370 | int dst_c = p / pixels_per_cluster; | 
|---|
|  | 371 | int dst_p = p % pixels_per_cluster; | 
|---|
|  | 372 | sum_p = sum_p + (int) TA(src_c, src_l, p + hrange) - (int) TA(src_c, src_l, 0); | 
|---|
|  | 373 | TB(dst_c, dst_p, l) = sum_p / hnorm; | 
|---|
|  | 374 | TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm; | 
|---|
|  | 375 | } | 
|---|
|  | 376 | // second domain : from (hrange+1) to (NP-hrange-1) | 
|---|
|  | 377 | for (p = hrange + 1; p < NP - hrange; p++) | 
|---|
|  | 378 | { | 
|---|
|  | 379 | // dst_c and dst_p are the cluster index and the pixel index for B | 
|---|
|  | 380 | int dst_c = p / pixels_per_cluster; | 
|---|
|  | 381 | int dst_p = p % pixels_per_cluster; | 
|---|
|  | 382 | sum_p = sum_p + (int) TA(src_c, src_l, p + hrange) | 
|---|
|  | 383 | - (int) TA(src_c, src_l, p - hrange - 1); | 
|---|
|  | 384 | TB(dst_c, dst_p, l) = sum_p / hnorm; | 
|---|
|  | 385 | TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm; | 
|---|
|  | 386 | } | 
|---|
|  | 387 | // third domain : from (NP-hrange) to (NP-1) | 
|---|
|  | 388 | for (p = NP - hrange; p < NP; p++) | 
|---|
|  | 389 | { | 
|---|
|  | 390 | // dst_c and dst_p are the cluster index and the pixel index for B | 
|---|
|  | 391 | int dst_c = p / pixels_per_cluster; | 
|---|
|  | 392 | int dst_p = p % pixels_per_cluster; | 
|---|
|  | 393 | sum_p = sum_p + (int) TA(src_c, src_l, NP - 1) | 
|---|
|  | 394 | - (int) TA(src_c, src_l, p - hrange - 1); | 
|---|
|  | 395 | TB(dst_c, dst_p, l) = sum_p / hnorm; | 
|---|
|  | 396 | TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm; | 
|---|
|  | 397 | } | 
|---|
|  | 398 |  | 
|---|
|  | 399 | #if SUPER_VERBOSE | 
|---|
|  | 400 | printf(" - line %d computed at cycle %d\n", l, giet_proctime() ); | 
|---|
|  | 401 | #endif | 
|---|
|  | 402 |  | 
|---|
|  | 403 | } | 
|---|
|  | 404 |  | 
|---|
|  | 405 | date  = giet_proctime(); | 
|---|
|  | 406 | H_END[cluster_id][lpid] = date; | 
|---|
|  | 407 |  | 
|---|
|  | 408 | #if VERBOSE | 
|---|
|  | 409 | printf( "\n[CONVOL] thread[%d,%d,%d] completes horizontal filter" | 
|---|
|  | 410 | " at cycle %d\n", | 
|---|
|  | 411 | x, y, lpid, date ); | 
|---|
|  | 412 | #else | 
|---|
|  | 413 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 414 | printf( "\n[CONVOL] thread[0,0,0] completes horizontal filter" | 
|---|
|  | 415 | " at cycle %d\n", date ); | 
|---|
|  | 416 | #endif | 
|---|
|  | 417 |  | 
|---|
|  | 418 | ///////////////////////////// | 
|---|
|  | 419 | #if USE_SQT_BARRIER | 
|---|
|  | 420 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 421 | #else | 
|---|
|  | 422 | barrier_wait( &barrier ); | 
|---|
|  | 423 | #endif | 
|---|
|  | 424 |  | 
|---|
|  | 425 |  | 
|---|
|  | 426 | /////////////////////////////////////////////////////////////// | 
|---|
|  | 427 | // parallel vertical filter : | 
|---|
|  | 428 | // C <= transpose(FV(B)) | 
|---|
|  | 429 | // Each thread computes (NP/nthreads) columns | 
|---|
|  | 430 | // The image must be extended : | 
|---|
|  | 431 | // if (l<0)    TB(cluster_id,p,l) == TB(cluster_id,p,0) | 
|---|
|  | 432 | // if (l>NL-1)   TB(cluster_id,p,l) == TB(cluster_id,p,NL-1) | 
|---|
|  | 433 | /////////////////////////////////////////////////////////////// | 
|---|
|  | 434 |  | 
|---|
|  | 435 | date  = giet_proctime(); | 
|---|
|  | 436 | V_BEG[cluster_id][lpid] = date; | 
|---|
|  | 437 |  | 
|---|
|  | 438 | #if VERBOSE | 
|---|
|  | 439 | printf( "\n[CONVOL] thread[%d,%d,%d] starts vertical filter" | 
|---|
|  | 440 | " at cycle %d\n", | 
|---|
|  | 441 | x, y, lpid, date ); | 
|---|
|  | 442 | #else | 
|---|
|  | 443 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 444 | printf( "\n[CONVOL] thread[0,0,0] starts vertical filter" | 
|---|
|  | 445 | " at cycle %d\n", date ); | 
|---|
|  | 446 | #endif | 
|---|
|  | 447 |  | 
|---|
|  | 448 | // l = absolute line index / p = absolute pixel index | 
|---|
|  | 449 | // first & last define which pixels are handled by a given thread | 
|---|
|  | 450 |  | 
|---|
|  | 451 | first = thread_id * pixels_per_thread; | 
|---|
|  | 452 | last  = first + pixels_per_thread; | 
|---|
|  | 453 |  | 
|---|
|  | 454 | for (p = first; p < last; p++) | 
|---|
|  | 455 | { | 
|---|
|  | 456 | // src_c and src_p are the cluster index and the pixel index for B | 
|---|
|  | 457 | int src_c = p / pixels_per_cluster; | 
|---|
|  | 458 | int src_p = p % pixels_per_cluster; | 
|---|
|  | 459 |  | 
|---|
|  | 460 | int sum_l; | 
|---|
|  | 461 |  | 
|---|
|  | 462 | // We use the specific values of the vertical ep-filter | 
|---|
|  | 463 | // To minimize the number of tests, the NL lines are split in three domains | 
|---|
|  | 464 |  | 
|---|
|  | 465 | // first domain : explicit computation for the first 18 values | 
|---|
|  | 466 | for (l = 0; l < 18; l++) | 
|---|
|  | 467 | { | 
|---|
|  | 468 | // dst_c and dst_l are the cluster index and the line index for C | 
|---|
|  | 469 | int dst_c = l / lines_per_cluster; | 
|---|
|  | 470 | int dst_l = l % lines_per_cluster; | 
|---|
|  | 471 |  | 
|---|
|  | 472 | for (z = 0, sum_l = 0; z < 35; z++) | 
|---|
|  | 473 | { | 
|---|
|  | 474 | sum_l = sum_l + vf[z] * TB(src_c, src_p, max(l - 17 + z,0) ); | 
|---|
|  | 475 | } | 
|---|
|  | 476 | TC(dst_c, dst_l, p) = sum_l / vnorm; | 
|---|
|  | 477 | } | 
|---|
|  | 478 | // second domain | 
|---|
|  | 479 | for (l = 18; l < NL - 17; l++) | 
|---|
|  | 480 | { | 
|---|
|  | 481 | // dst_c and dst_l are the cluster index and the line index for C | 
|---|
|  | 482 | int dst_c = l / lines_per_cluster; | 
|---|
|  | 483 | int dst_l = l % lines_per_cluster; | 
|---|
|  | 484 |  | 
|---|
|  | 485 | sum_l = sum_l + TB(src_c, src_p, l + 4) | 
|---|
|  | 486 | + TB(src_c, src_p, l + 8) | 
|---|
|  | 487 | + TB(src_c, src_p, l + 11) | 
|---|
|  | 488 | + TB(src_c, src_p, l + 15) | 
|---|
|  | 489 | + TB(src_c, src_p, l + 17) | 
|---|
|  | 490 | - TB(src_c, src_p, l - 5) | 
|---|
|  | 491 | - TB(src_c, src_p, l - 9) | 
|---|
|  | 492 | - TB(src_c, src_p, l - 12) | 
|---|
|  | 493 | - TB(src_c, src_p, l - 16) | 
|---|
|  | 494 | - TB(src_c, src_p, l - 18); | 
|---|
|  | 495 |  | 
|---|
|  | 496 | TC(dst_c, dst_l, p) = sum_l / vnorm; | 
|---|
|  | 497 | } | 
|---|
|  | 498 | // third domain | 
|---|
|  | 499 | for (l = NL - 17; l < NL; l++) | 
|---|
|  | 500 | { | 
|---|
|  | 501 | // dst_c and dst_l are the cluster index and the line index for C | 
|---|
|  | 502 | int dst_c = l / lines_per_cluster; | 
|---|
|  | 503 | int dst_l = l % lines_per_cluster; | 
|---|
|  | 504 |  | 
|---|
|  | 505 | sum_l = sum_l + TB(src_c, src_p, min(l + 4, NL - 1)) | 
|---|
|  | 506 | + TB(src_c, src_p, min(l + 8, NL - 1)) | 
|---|
|  | 507 | + TB(src_c, src_p, min(l + 11, NL - 1)) | 
|---|
|  | 508 | + TB(src_c, src_p, min(l + 15, NL - 1)) | 
|---|
|  | 509 | + TB(src_c, src_p, min(l + 17, NL - 1)) | 
|---|
|  | 510 | - TB(src_c, src_p, l - 5) | 
|---|
|  | 511 | - TB(src_c, src_p, l - 9) | 
|---|
|  | 512 | - TB(src_c, src_p, l - 12) | 
|---|
|  | 513 | - TB(src_c, src_p, l - 16) | 
|---|
|  | 514 | - TB(src_c, src_p, l - 18); | 
|---|
|  | 515 |  | 
|---|
|  | 516 | TC(dst_c, dst_l, p) = sum_l / vnorm; | 
|---|
|  | 517 | } | 
|---|
|  | 518 |  | 
|---|
|  | 519 | #if SUPER_VERBOSE | 
|---|
|  | 520 | printf(" - column %d computed at cycle %d\n", p, giet_proctime()); | 
|---|
|  | 521 | #endif | 
|---|
|  | 522 |  | 
|---|
|  | 523 | } | 
|---|
|  | 524 |  | 
|---|
|  | 525 | date  = giet_proctime(); | 
|---|
|  | 526 | V_END[cluster_id][lpid] = date; | 
|---|
|  | 527 |  | 
|---|
|  | 528 | #if VERBOSE | 
|---|
|  | 529 | printf( "\n[CONVOL] thread[%d,%d,%d] completes vertical filter" | 
|---|
|  | 530 | " at cycle %d\n", | 
|---|
|  | 531 | x, y, lpid, date ); | 
|---|
|  | 532 | #else | 
|---|
|  | 533 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 534 | printf( "\n[CONVOL] thread[0,0,0] completes vertical filter" | 
|---|
|  | 535 | " at cycle %d\n", date ); | 
|---|
|  | 536 | #endif | 
|---|
|  | 537 |  | 
|---|
|  | 538 | //////////////////////////// | 
|---|
|  | 539 | #if USE_SQT_BARRIER | 
|---|
|  | 540 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 541 | #else | 
|---|
|  | 542 | barrier_wait( &barrier ); | 
|---|
|  | 543 | #endif | 
|---|
|  | 544 |  | 
|---|
|  | 545 | //////////////////////////////////////////////////////////////////////// | 
|---|
|  | 546 | // Optional parallel display of the final image Z <= D + C | 
|---|
|  | 547 | // Eah thread[x,y,p] displays (NL/nthreads) lines. (one byte per pixel). | 
|---|
|  | 548 | //////////////////////////////////////////////////////////////////////// | 
|---|
|  | 549 |  | 
|---|
|  | 550 | if ( FINAL_DISPLAY_ENABLE ) | 
|---|
|  | 551 | { | 
|---|
|  | 552 | date  = giet_proctime(); | 
|---|
|  | 553 | D_BEG[cluster_id][lpid] = date; | 
|---|
|  | 554 |  | 
|---|
|  | 555 | #if VERBOSE | 
|---|
|  | 556 | printf( "\n[CONVOL] thread[%d,%d,%d] starts final display" | 
|---|
|  | 557 | " at cycle %d\n", | 
|---|
|  | 558 | x, y, lpid, date); | 
|---|
|  | 559 | #else | 
|---|
|  | 560 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 561 | printf( "\n[CONVOL] thread[0,0,0] starts final display" | 
|---|
|  | 562 | " at cycle %d\n", date ); | 
|---|
|  | 563 | #endif | 
|---|
|  | 564 |  | 
|---|
|  | 565 | unsigned int line; | 
|---|
|  | 566 | unsigned int offset = lines_per_thread * lpid; | 
|---|
|  | 567 |  | 
|---|
|  | 568 | for ( l = 0 ; l < lines_per_thread ; l++ ) | 
|---|
|  | 569 | { | 
|---|
|  | 570 | line = offset + l; | 
|---|
|  | 571 |  | 
|---|
|  | 572 | for ( p = 0 ; p < NP ; p++ ) | 
|---|
|  | 573 | { | 
|---|
|  | 574 | TZ(cluster_id, line, p) = | 
|---|
|  | 575 | (unsigned char)( (TD(cluster_id, line, p) + | 
|---|
|  | 576 | TC(cluster_id, line, p) ) >> 8 ); | 
|---|
|  | 577 | } | 
|---|
|  | 578 |  | 
|---|
|  | 579 | giet_fbf_sync_write( NP*(l + (thread_id * lines_per_thread) ), | 
|---|
|  | 580 | &TZ(cluster_id, line, 0), | 
|---|
|  | 581 | NP); | 
|---|
|  | 582 | } | 
|---|
|  | 583 |  | 
|---|
|  | 584 | date  = giet_proctime(); | 
|---|
|  | 585 | D_END[cluster_id][lpid] = date; | 
|---|
|  | 586 |  | 
|---|
|  | 587 | #if VERBOSE | 
|---|
|  | 588 | printf( "\n[CONVOL] thread[%d,%d,%d] completes final display" | 
|---|
|  | 589 | " at cycle %d\n", | 
|---|
|  | 590 | x, y, lpid, date); | 
|---|
|  | 591 | #else | 
|---|
|  | 592 | if ( (x==0) && (y==0) && (lpid==0) ) | 
|---|
|  | 593 | printf( "\n[CONVOL] thread[0,0,0] completes final display" | 
|---|
|  | 594 | " at cycle %d\n", date ); | 
|---|
|  | 595 | #endif | 
|---|
|  | 596 |  | 
|---|
|  | 597 | ////////////////////////////// | 
|---|
|  | 598 | #if USE_SQT_BARRIER | 
|---|
|  | 599 | sqt_barrier_wait( &barrier ); | 
|---|
|  | 600 | #else | 
|---|
|  | 601 | barrier_wait( &barrier ); | 
|---|
|  | 602 | #endif | 
|---|
|  | 603 |  | 
|---|
|  | 604 | } | 
|---|
|  | 605 |  | 
|---|
|  | 606 | // all threads (but the one executing main) exit | 
|---|
|  | 607 | if ( (x!=0) || (y!=0) || (lpid!=0) ) | 
|---|
|  | 608 | { | 
|---|
|  | 609 | giet_pthread_exit( "completed"); | 
|---|
|  | 610 | } | 
|---|
|  | 611 |  | 
|---|
|  | 612 | } // end execute() | 
|---|
|  | 613 |  | 
|---|
|  | 614 |  | 
|---|
|  | 615 |  | 
|---|
|  | 616 | ///////////////////////////////////////// | 
|---|
|  | 617 | void instrument( unsigned int nclusters, | 
|---|
|  | 618 | unsigned int nprocs ) | 
|---|
|  | 619 | ///////////////////////////////////////// | 
|---|
|  | 620 | { | 
|---|
|  | 621 | int cc, pp; | 
|---|
|  | 622 |  | 
|---|
|  | 623 | unsigned int min_start = 0xFFFFFFFF; | 
|---|
|  | 624 | unsigned int max_start = 0; | 
|---|
|  | 625 |  | 
|---|
|  | 626 | unsigned int min_h_beg = 0xFFFFFFFF; | 
|---|
|  | 627 | unsigned int max_h_beg = 0; | 
|---|
|  | 628 |  | 
|---|
|  | 629 | unsigned int min_h_end = 0xFFFFFFFF; | 
|---|
|  | 630 | unsigned int max_h_end = 0; | 
|---|
|  | 631 |  | 
|---|
|  | 632 | unsigned int min_v_beg = 0xFFFFFFFF; | 
|---|
|  | 633 | unsigned int max_v_beg = 0; | 
|---|
|  | 634 |  | 
|---|
|  | 635 | unsigned int min_v_end = 0xFFFFFFFF; | 
|---|
|  | 636 | unsigned int max_v_end = 0; | 
|---|
|  | 637 |  | 
|---|
|  | 638 | unsigned int min_d_beg = 0xFFFFFFFF; | 
|---|
|  | 639 | unsigned int max_d_beg = 0; | 
|---|
|  | 640 |  | 
|---|
|  | 641 | unsigned int min_d_end = 0xFFFFFFFF; | 
|---|
|  | 642 | unsigned int max_d_end = 0; | 
|---|
|  | 643 |  | 
|---|
|  | 644 | for (cc = 0; cc < nclusters; cc++) | 
|---|
|  | 645 | { | 
|---|
|  | 646 | for (pp = 0; pp < nprocs; pp++ ) | 
|---|
|  | 647 | { | 
|---|
|  | 648 | if (START[cc][pp] < min_start) min_start = START[cc][pp]; | 
|---|
|  | 649 | if (START[cc][pp] > max_start) max_start = START[cc][pp]; | 
|---|
|  | 650 |  | 
|---|
|  | 651 | if (H_BEG[cc][pp] < min_h_beg) min_h_beg = H_BEG[cc][pp]; | 
|---|
|  | 652 | if (H_BEG[cc][pp] > max_h_beg) max_h_beg = H_BEG[cc][pp]; | 
|---|
|  | 653 |  | 
|---|
|  | 654 | if (H_END[cc][pp] < min_h_end) min_h_end = H_END[cc][pp]; | 
|---|
|  | 655 | if (H_END[cc][pp] > max_h_end) max_h_end = H_END[cc][pp]; | 
|---|
|  | 656 |  | 
|---|
|  | 657 | if (V_BEG[cc][pp] < min_v_beg) min_v_beg = V_BEG[cc][pp]; | 
|---|
|  | 658 | if (V_BEG[cc][pp] > max_v_beg) max_v_beg = V_BEG[cc][pp]; | 
|---|
|  | 659 |  | 
|---|
|  | 660 | if (V_END[cc][pp] < min_v_end) min_v_end = V_END[cc][pp]; | 
|---|
|  | 661 | if (V_END[cc][pp] > max_v_end) max_v_end = V_END[cc][pp]; | 
|---|
|  | 662 |  | 
|---|
|  | 663 | if (D_BEG[cc][pp] < min_d_beg) min_d_beg = D_BEG[cc][pp]; | 
|---|
|  | 664 | if (D_BEG[cc][pp] > max_d_beg) max_d_beg = D_BEG[cc][pp]; | 
|---|
|  | 665 |  | 
|---|
|  | 666 | if (D_END[cc][pp] < min_d_end) min_d_end = D_END[cc][pp]; | 
|---|
|  | 667 | if (D_END[cc][pp] > max_d_end) max_d_end = D_END[cc][pp]; | 
|---|
|  | 668 | } | 
|---|
|  | 669 | } | 
|---|
|  | 670 |  | 
|---|
|  | 671 | printf(" - START : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 672 | min_start, max_start, (min_start+max_start)/2, max_start-min_start); | 
|---|
|  | 673 |  | 
|---|
|  | 674 | printf(" - H_BEG : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 675 | min_h_beg, max_h_beg, (min_h_beg+max_h_beg)/2, max_h_beg-min_h_beg); | 
|---|
|  | 676 |  | 
|---|
|  | 677 | printf(" - H_END : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 678 | min_h_end, max_h_end, (min_h_end+max_h_end)/2, max_h_end-min_h_end); | 
|---|
|  | 679 |  | 
|---|
|  | 680 | printf(" - V_BEG : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 681 | min_v_beg, max_v_beg, (min_v_beg+max_v_beg)/2, max_v_beg-min_v_beg); | 
|---|
|  | 682 |  | 
|---|
|  | 683 | printf(" - V_END : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 684 | min_v_end, max_v_end, (min_v_end+max_v_end)/2, max_v_end-min_v_end); | 
|---|
|  | 685 |  | 
|---|
|  | 686 | printf(" - D_BEG : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 687 | min_d_beg, max_d_beg, (min_d_beg+max_d_beg)/2, max_d_beg-min_d_beg); | 
|---|
|  | 688 |  | 
|---|
|  | 689 | printf(" - D_END : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
|  | 690 | min_d_end, max_d_end, (min_d_end+max_d_end)/2, max_d_end-min_d_end); | 
|---|
|  | 691 |  | 
|---|
|  | 692 | printf( "\n General Scenario (Kcycles for each step)\n" ); | 
|---|
|  | 693 | printf( " - BOOT OS           = %d\n", (min_start            )/1000 ); | 
|---|
|  | 694 | printf( " - LOAD IMAGE        = %d\n", (min_h_beg - min_start)/1000 ); | 
|---|
|  | 695 | printf( " - H_FILTER          = %d\n", (max_h_end - min_h_beg)/1000 ); | 
|---|
|  | 696 | printf( " - BARRIER HORI/VERT = %d\n", (min_v_beg - max_h_end)/1000 ); | 
|---|
|  | 697 | printf( " - V_FILTER          = %d\n", (max_v_end - min_v_beg)/1000 ); | 
|---|
|  | 698 | printf( " - BARRIER VERT/DISP = %d\n", (min_d_beg - max_v_end)/1000 ); | 
|---|
|  | 699 | printf( " - DISPLAY           = %d\n", (max_d_end - min_d_beg)/1000 ); | 
|---|
|  | 700 |  | 
|---|
|  | 701 | } // end instrument() | 
|---|
|  | 702 |  | 
|---|
|  | 703 |  | 
|---|
|  | 704 |  | 
|---|
|  | 705 | /////////////////////////////////////////// | 
|---|
|  | 706 | __attribute__ ((constructor)) void main() | 
|---|
|  | 707 | /////////////////////////////////////////// | 
|---|
|  | 708 | { | 
|---|
|  | 709 | // get plat-form parameters | 
|---|
|  | 710 | unsigned int x_size;                 // number of clusters in a row | 
|---|
|  | 711 | unsigned int y_size;                 // number of clusters in a column | 
|---|
|  | 712 | unsigned int nprocs;                 // number of processors per cluster | 
|---|
|  | 713 | giet_procs_number( &x_size , &y_size , &nprocs ); | 
|---|
|  | 714 |  | 
|---|
|  | 715 | // processor identifiers | 
|---|
|  | 716 | unsigned int x;                      // x coordinate | 
|---|
|  | 717 | unsigned int y;                      // y coordinate | 
|---|
|  | 718 | unsigned int lpid;                   // local proc index | 
|---|
|  | 719 | giet_proc_xyp( &x, &y, &lpid ); | 
|---|
|  | 720 |  | 
|---|
|  | 721 | // indexes for loops | 
|---|
|  | 722 | unsigned int cx; | 
|---|
|  | 723 | unsigned int cy; | 
|---|
|  | 724 | unsigned int n; | 
|---|
|  | 725 |  | 
|---|
|  | 726 | unsigned int nclusters  = x_size * y_size; | 
|---|
|  | 727 | unsigned int nthreads   = nclusters * nprocs; | 
|---|
|  | 728 |  | 
|---|
| [718] | 729 | // get a shared TTY | 
|---|
|  | 730 | giet_tty_alloc( 1 ); | 
|---|
|  | 731 | lock_init( &tty_lock ); | 
|---|
|  | 732 |  | 
|---|
|  | 733 | // get FBF size | 
|---|
|  | 734 | unsigned int  width; | 
|---|
|  | 735 | unsigned int  height; | 
|---|
|  | 736 | giet_fbf_size( &width , &height ); | 
|---|
|  | 737 |  | 
|---|
| [708] | 738 | // parameters checking | 
|---|
| [718] | 739 | if ( (width != NP) || (height != NL) ) | 
|---|
|  | 740 | giet_pthread_exit( "[CONVOL ERROR] FBF size must be NP * NL\n"); | 
|---|
| [708] | 741 | if ((nprocs != 1) && (nprocs != 2) && (nprocs != 4) && (nprocs != 8)) | 
|---|
|  | 742 | giet_pthread_exit( "[CONVOL ERROR] NB_PROCS_MAX must be 1, 2, 4 or 8\n"); | 
|---|
|  | 743 |  | 
|---|
|  | 744 | if ((x_size!=1) && (x_size!=2) && (x_size!=4) && (x_size!=8) && (x_size!=16)) | 
|---|
|  | 745 | giet_pthread_exit( "[CONVOL ERROR] X_SIZE must be 1, 2, 4, 8, 16\n"); | 
|---|
|  | 746 |  | 
|---|
|  | 747 | if ((y_size!=1) && (y_size!=2) && (y_size!=4) && (y_size!=8) && (y_size!=16)) | 
|---|
|  | 748 | giet_pthread_exit( "[CONVOL ERROR] Y_SIZE must be 1, 2, 4, 8, 16\n"); | 
|---|
|  | 749 |  | 
|---|
|  | 750 | if ( NL % nclusters != 0 ) | 
|---|
|  | 751 | giet_pthread_exit( "[CONVOL ERROR] X_SIZE*Y_SIZE must be a divider of NL"); | 
|---|
|  | 752 |  | 
|---|
|  | 753 | if ( NP % nclusters != 0 ) | 
|---|
|  | 754 | giet_pthread_exit( "[CONVOL ERROR] X_SIZE*Y_SIZE must be a divider of NP"); | 
|---|
|  | 755 |  | 
|---|
| [718] | 756 | // get FBF ownership | 
|---|
|  | 757 | giet_fbf_alloc(); | 
|---|
|  | 758 |  | 
|---|
| [708] | 759 | // initializes the distributed heap[x,y] | 
|---|
|  | 760 | for ( cx = 0 ; cx < x_size ; cx++ ) | 
|---|
|  | 761 | { | 
|---|
|  | 762 | for ( cy = 0 ; cy < y_size ; cy++ ) | 
|---|
|  | 763 | { | 
|---|
|  | 764 | heap_init( cx , cy ); | 
|---|
|  | 765 | } | 
|---|
|  | 766 | } | 
|---|
|  | 767 |  | 
|---|
|  | 768 | // allocate trdid[] array | 
|---|
|  | 769 | pthread_t* trdid = malloc( nthreads * sizeof(pthread_t) ); | 
|---|
|  | 770 |  | 
|---|
|  | 771 | // barrier initialisation | 
|---|
|  | 772 | #if USE_SQT_BARRIER | 
|---|
|  | 773 | sqt_barrier_init( &barrier, x_size , y_size , nprocs ); | 
|---|
|  | 774 | #else | 
|---|
|  | 775 | barrier_init( &barrier, nthreads ); | 
|---|
|  | 776 | #endif | 
|---|
|  | 777 |  | 
|---|
|  | 778 | printf("\n[CONVOL] thread[0,0,0] completes initialisation at cycle %d\n" | 
|---|
|  | 779 | "- CLUSTERS     = %d\n" | 
|---|
|  | 780 | "- PROCS        = %d\n" | 
|---|
|  | 781 | "- THREADS      = %d\n", | 
|---|
|  | 782 | giet_proctime(), nclusters, nprocs, nthreads ); | 
|---|
|  | 783 |  | 
|---|
|  | 784 | // launch other threads to run execute() function | 
|---|
|  | 785 | for ( n = 1 ; n < nthreads ; n++ ) | 
|---|
|  | 786 | { | 
|---|
|  | 787 | if ( giet_pthread_create( &trdid[n], | 
|---|
|  | 788 | NULL,                  // no attribute | 
|---|
|  | 789 | &execute, | 
|---|
|  | 790 | NULL ) )               // no argument | 
|---|
|  | 791 | { | 
|---|
|  | 792 | printf("\n[TRANSPOSE ERROR] creating thread %x\n", trdid[n] ); | 
|---|
|  | 793 | giet_pthread_exit( NULL ); | 
|---|
|  | 794 | } | 
|---|
|  | 795 | } | 
|---|
|  | 796 |  | 
|---|
|  | 797 | // run the execute() function | 
|---|
|  | 798 | execute(); | 
|---|
|  | 799 |  | 
|---|
|  | 800 | // wait other threads completion | 
|---|
|  | 801 | for ( n = 1 ; n < nthreads ; n++ ) | 
|---|
|  | 802 | { | 
|---|
|  | 803 | if ( giet_pthread_join( trdid[n], NULL ) ) | 
|---|
|  | 804 | { | 
|---|
|  | 805 | printf("\n[TRANSPOSE ERROR] joining thread %x\n", trdid[n] ); | 
|---|
|  | 806 | giet_pthread_exit( NULL ); | 
|---|
|  | 807 | } | 
|---|
|  | 808 | else | 
|---|
|  | 809 | { | 
|---|
|  | 810 | printf("\n[TRANSPOSE] thread %x joined at cycle %d\n", | 
|---|
|  | 811 | trdid[n] , giet_proctime() ); | 
|---|
|  | 812 | } | 
|---|
|  | 813 | } | 
|---|
|  | 814 |  | 
|---|
|  | 815 | // call the instrument() function | 
|---|
|  | 816 | instrument( nclusters , nprocs ); | 
|---|
|  | 817 |  | 
|---|
|  | 818 | giet_pthread_exit( "completed" ); | 
|---|
|  | 819 |  | 
|---|
|  | 820 | } // end main() | 
|---|
|  | 821 |  | 
|---|
|  | 822 |  | 
|---|
|  | 823 |  | 
|---|
|  | 824 | // Local Variables: | 
|---|
|  | 825 | // tab-width: 3 | 
|---|
|  | 826 | // c-basic-offset: 3 | 
|---|
|  | 827 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
|  | 828 | // indent-tabs-mode: nil | 
|---|
|  | 829 | // End: | 
|---|
|  | 830 |  | 
|---|
|  | 831 | // vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3 | 
|---|
|  | 832 |  | 
|---|
|  | 833 |  | 
|---|