/* * The argv argument will be populated with the address that the PPE provided, * from the 4th argument to spe_context_run() */ int main(uint64_t speid, uint64_t argv, uint64_t envp) { struct spe_args args __attribute__((aligned(SPE_ALIGN))); mfc_get(&args, argv, sizeof(args), 0, 0, 0); mfc_write_tag_mask(1 << 0); mfc_read_tag_status_all(); cmap_calls = 0; dma_puts = 0; spu_write_decrementer(-1); // Run multiple renders with offsets. Should be factored into render_fractal() render_fractal(&args.fractal, args.thread_idx, args.n_threads, 0.); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta * 7 / 8); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta * 3 / 4); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta * 5 / 8); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta / 2); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta * 3 / 8); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta / 4); render_fractal(&args.fractal, args.thread_idx, args.n_threads, args.fractal.delta / 8); // Send remaining points if(fill%2048) { // select the last buffer used int f = fill / 2048; mfc_put(&points[f*2048], (uint)args.fractal.pointbuf[f], 16384, 0, 0, 0); // Block for completion mfc_write_tag_mask(1<<0); mfc_read_tag_status_all(); // Send a message with top bit set to indicate final item spu_write_out_intr_mbox((1<<31)|f); // Send another message indicating count spu_write_out_intr_mbox(fill%2048); ++dma_puts; } // Report some stats uint ticks = -1 - spu_read_decrementer(); printf("cmap calls %d ticks %u calls/tick %f\n", cmap_calls, ticks, (double)cmap_calls/ticks ); printf("dma puts %d\n", dma_puts); return 0; }
int main() { while (1){ int res; ppu_addr_t program_data_ea = spu_read_in_mbox(); program_data_ea += ((ppu_addr_t)spu_read_in_mbox())<<32; res = handleCommand( program_data_ea ); // spu_write_out_mbox( res ); spu_write_out_intr_mbox( res ); } return 0; }
/* Sends a message to PPU that the current frame has been processed */ static void send_frame_done(ppu_data_t ppu_data, int frame_id) { uint32_t mbox_message = SPU_FRAME_DONE; while (spu_stat_out_intr_mbox() <= 0) ; spu_write_out_intr_mbox(mbox_message); dprintf("SPU[%d]: Finished frame %d. Informed PPU\n", ppu_data.spe_id, frame_id + 1); /* Suppress warnings of unused */ ppu_data.spe_id = ppu_data.spe_id; frame_id = frame_id; }
int main(uint64_t speid, uint64_t argp, uint64_t envp){ unsigned int data[NUM_STREAMS]; unsigned int num_spus = (unsigned int)argp, i, num_images; struct image my_image __attribute__ ((aligned(16))); int mode = (int)envp; speid = speid; //get rid of warning while(1){ num_images = 0; for (i = 0; i < NUM_STREAMS / num_spus; i++){ //assume NUM_STREAMS is a multiple of num_spus while(spu_stat_in_mbox() == 0); data[i] = spu_read_in_mbox(); if (!data[i]) return 0; num_images++; } for (i = 0; i < num_images; i++){ mfc_get(&my_image, data[i], sizeof(struct image), MY_TAG, 0, 0); mfc_write_tag_mask(1 << MY_TAG); mfc_read_tag_status_all(); switch(mode){ default: case MODE_SIMPLE: process_image_simple(&my_image); break; case MODE_2LINES: process_image_2lines(&my_image); break; case MODE_DOUBLE: process_image_double(&my_image); break; case MODE_DMALIST: process_image_dmalist(&my_image); break; } } data[0] = DONE; spu_write_out_intr_mbox(data[0]); } return 0; }
int main (unsigned long long speid, unsigned long long argp, unsigned long long envp) { /* Signal to PPU side that it should fork now. */ spu_write_out_intr_mbox (0); /* Wait until fork completed. */ spu_read_in_mbox (); /* Trigger watchpoint. */ var = 1; /* Now call some function to trigger breakpoint. */ func (); return 0; }
void terminal_func () { spu_write_out_intr_mbox (0); spu_read_in_mbox (); }
/* * Colour the given framebuffer address pix. * i and params may be used to select the colour. */ static void write_colour(struct pixel *pix, float i, struct fractal_params *params) { // Mask for keeping track of ppe finishing with buffers static int valid = 0xff; static vector unsigned int sentinel = {1,0,0,0}; ++cmap_calls; uint colour; // Various colouring alternatives are possible here // ignore the first few steps - reduces backgroud noise if(i<20) return; /* if(i==0) return; if(params->i_max < 10000) { colour = 0x00010000; } else if(params->i_max < 20000) { if(i<10000) return; colour = 0x00000200; } else { if(i<20000) return; colour = 0x00000004; }*/ colour = 0x00010100; // If starting to fill a new buffer, check that any earlier use // is finished with - ppe signals completion if(fill%2048 == 0) { while(!(valid&(1<<(fill/2048)))) { valid |= spu_read_signal1(); } } // set values points[fill].addr = (uint*)pix; points[fill].i = colour; ++fill; // if we just filled a buffer, send it to ppe if(fill%2048==0) { // select the specific buffer that is full int f = (fill / 2048) - 1; mfc_put(&points[f*2048], (uint)params->pointbuf[f], 16384, 0, 0, 0); // fence a sentinel - the ppe will spin on this completing... // What's a better way to achieve sync? mfc_putf(&sentinel, (uint)params->sentinel[f], 16, 0, 0, 0); // interrupt the ppe spu_write_out_intr_mbox(f); // unmask the relevant bit valid&=~(1<<f); if(fill==16384) { fill = 0; } ++dma_puts; } }
void work(param_t param) { printf("SPU[%u] work()\n", param.proc); unsigned int inbox, offset; unsigned int *in = malloc_align(param.bitset_size, ALIGN_EXP); unsigned int *out = malloc_align(param.bitset_size, ALIGN_EXP); unsigned int *use = malloc_align(param.bitset_size, ALIGN_EXP); unsigned int *def = malloc_align(param.bitset_size, ALIGN_EXP); if(in == NULL || out == NULL || use == NULL || def == NULL) { printf("malloc_align() failed\n"); exit(1); } unsigned tag_1, tag_2, tag_3, tag_4; unsigned int tag_id; /* Reserve a tag for application usage */ if ((tag_1 = mfc_tag_reserve()) == MFC_TAG_INVALID) { printf("ERROR: unable to reserve a tag_1\n"); } if ((tag_2 = mfc_tag_reserve()) == MFC_TAG_INVALID) { printf("ERROR: unable to reserve a tag_2\n"); } if ((tag_3 = mfc_tag_reserve()) == MFC_TAG_INVALID) { printf("ERROR: unable to reserve a tag_3\n"); } if ((tag_4 = mfc_tag_reserve()) == MFC_TAG_INVALID) { printf("ERROR: unable to reserve a tag_4\n"); } while(1) { inbox = spu_read_in_mbox(); if(inbox == UINT_MAX) { printf("SPU[%u] received exit signal.. exiting.\n", param.proc); return; } offset = param.bitset_subsets*inbox; mfc_get(in, (unsigned int) (param.bs_in_addr + offset), param.bitset_size, tag_1, 0, 0); mfc_get(out, (unsigned int) (param.bs_out_addr + offset), param.bitset_size, tag_2, 0, 0); mfc_get(use, (unsigned int) (param.bs_use_addr + offset), param.bitset_size, tag_3, 0, 0); mfc_get(def, (unsigned int) (param.bs_def_addr + offset), param.bitset_size, tag_4, 0, 0); mfc_write_tag_mask(1 << tag_1 | 1 << tag_2 | 1 << tag_3 | 1 << tag_4); mfc_read_tag_status_all(); D(printf("SPU[%d] index: %u bitset_subsets: %u offset: %u\n", param.proc, inbox, param.bitset_subsets, offset); printf("SPU[%d]\t&use: %p\n\t&def: %p\n\t&out: %p\n\t&in: %p\n", param.proc, (void*)param.bs_use_addr, (void*)param.bs_def_addr, (void*)param.bs_out_addr, (void*)param.bs_in_addr); void *tmp_ptr = (void*) (param.bs_use_addr + offset); printf("SPU[%d] read\t\t&%p = use(%p)={", param.proc, (void*)use, tmp_ptr); for (int i = 0; i < 100; ++i){ if ( bitset_get_bit(use, i) ) { printf("%d ", i); } } printf("}\n"); tmp_ptr = (void*) (param.bs_def_addr + offset); printf("SPU[%d] read\t\t&%p = def(%p)={", param.proc, (void*)def, tmp_ptr); for (int i = 0; i < 100; ++i){ if ( bitset_get_bit(def, i) ) { printf("%d ", i); } } printf("}\n"); tmp_ptr = (void*) (param.bs_out_addr + offset); printf("SPU[%d] read\t\t&%p = out(%p)={", param.proc, (void*)out, tmp_ptr); for (int i = 0; i < 100; ++i){ if ( bitset_get_bit(out, i) ) { printf("%d ", i); } } printf("}\n"); tmp_ptr = (void*) (param.bs_in_addr + offset); printf("SPU[%d] read\t\t&%p = in (%p)={", param.proc, (void*)in, tmp_ptr); for (int i = 0; i < 100; ++i){ if ( bitset_get_bit(in, i) ) { printf("%d ", i); } } printf("}\n")); bitset_megaop(param, in, out, use, def); D(printf("SPU[%d] calculated\tin={", param.proc); for (int i = 0; i < 100; ++i){ if ( bitset_get_bit(in, i) ) { printf("%d ", i); } } printf("}\n");) mfc_put(in, (unsigned int) (param.bs_in_addr + offset), param.bitset_size, tag_1, 0, 0); mfc_write_tag_mask(1 << tag_1); mfc_read_tag_status_all(); spu_write_out_intr_mbox(inbox); }