summaryrefslogtreecommitdiff
path: root/gcell/lib/runtime/spu
diff options
context:
space:
mode:
Diffstat (limited to 'gcell/lib/runtime/spu')
-rw-r--r--gcell/lib/runtime/spu/.gitignore10
-rw-r--r--gcell/lib/runtime/spu/gc_delay.c58
-rw-r--r--gcell/lib/runtime/spu/gc_logging.c77
-rw-r--r--gcell/lib/runtime/spu/gc_main.c731
-rw-r--r--gcell/lib/runtime/spu/gc_random.c44
-rw-r--r--gcell/lib/runtime/spu/gc_spu_config.h39
-rw-r--r--gcell/lib/runtime/spu/gc_spu_jd_queue.c123
-rw-r--r--gcell/lib/runtime/spu/gcell_runtime_qa.c105
-rw-r--r--gcell/lib/runtime/spu/spu_buffers.c35
-rw-r--r--gcell/lib/runtime/spu/spu_buffers.h32
10 files changed, 0 insertions, 1254 deletions
diff --git a/gcell/lib/runtime/spu/.gitignore b/gcell/lib/runtime/spu/.gitignore
deleted file mode 100644
index 36b575570..000000000
--- a/gcell/lib/runtime/spu/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-/Makefile
-/Makefile.in
-/*.a
-/*.la
-/*.lo
-/.deps
-/.libs
-/test_spu
-/gcell_spu_main
-/gcell_qa
diff --git a/gcell/lib/runtime/spu/gc_delay.c b/gcell/lib/runtime/spu/gc_delay.c
deleted file mode 100644
index 4d58935aa..000000000
--- a/gcell/lib/runtime/spu/gc_delay.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/spu/gc_delay.h>
-#include <gcell/compiler.h>
-
-inline static void
-gc_udelay_1us(void)
-{
- unsigned int i = 158;
-
- do { // 20 clocks per iteration of the loop
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127; nop $127; nop $127; nop $127");
- asm ("nop $127; nop $127");
- } while(--i != 0);
-}
-
-void
-gc_udelay(unsigned int usecs)
-{
- unsigned int i;
- for (i = 0; i < usecs; i++)
- gc_udelay_1us();
-}
-
-void
-gc_cdelay(unsigned int cpu_cycles)
-{
- if (cpu_cycles < 40) // roughly the amount of overhead
- return;
-
- cpu_cycles >>= 2; // about 4 cycles / loop
-
- while (cpu_cycles-- != 0){
- asm ("nop $127"); // keeps compiler from removing the loop
- }
-}
-
diff --git a/gcell/lib/runtime/spu/gc_logging.c b/gcell/lib/runtime/spu/gc_logging.c
deleted file mode 100644
index 48b7e5f25..000000000
--- a/gcell/lib/runtime/spu/gc_logging.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_logging.h>
-#include <gcell/gc_spu_args.h>
-#include <spu_intrinsics.h>
-#include <spu_mfcio.h>
-
-static gc_eaddr_t log_base_ea; // base address of log entries in EA
-static uint32_t log_idx_mask; // nentries - 1
-static uint32_t log_idx; // current log entry index
-static uint32_t log_seqno;
-
-static int log_tags; // two consecutive tags
-static int tmp_buffer_busy; // bitmask: buffer busy state
-static int tmp_buffer_idx; // 0 or 1
-static gc_log_entry_t tmp_buffer[2];
-
-void
-_gc_log_init(gc_log_t info)
-{
- spu_write_decrementer(~0);
-
- log_base_ea = info.base;
- log_idx_mask = info.nentries - 1;
- log_idx = 0;
- log_seqno = 0;
-
- log_tags = mfc_multi_tag_reserve(2);
- tmp_buffer_busy = 0;
- tmp_buffer_idx = 0;
-
- gc_log_write0(GCL_SS_SYS, 0);
-}
-
-void
-_gc_log_write(gc_log_entry_t entry)
-{
- if (log_base_ea == 0)
- return;
-
- entry.seqno = log_seqno++;
- entry.timestamp = spu_read_decrementer();
-
- if (tmp_buffer_busy & (1 << tmp_buffer_idx)){
- mfc_write_tag_mask(1 << (log_tags + tmp_buffer_idx));
- mfc_read_tag_status_all();
- }
-
- tmp_buffer[tmp_buffer_idx] = entry; // save local copy
-
- mfc_put(&tmp_buffer[tmp_buffer_idx],
- log_base_ea + log_idx * sizeof(entry), sizeof(entry),
- log_tags + tmp_buffer_idx, 0, 0);
-
- tmp_buffer_busy |= (1 << tmp_buffer_idx);
- tmp_buffer_idx ^= 0x1;
- log_idx = (log_idx + 1) & log_idx_mask;
-}
diff --git a/gcell/lib/runtime/spu/gc_main.c b/gcell/lib/runtime/spu/gc_main.c
deleted file mode 100644
index ba56e40f6..000000000
--- a/gcell/lib/runtime/spu/gc_main.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-// #define ENABLE_GC_LOGGING // define to enable logging
-
-#include <spu_intrinsics.h>
-#include <spu_mfcio.h>
-#include <sync_utils.h>
-#include "gc_spu_config.h"
-#include "spu_buffers.h"
-#include <gcell/gc_spu_args.h>
-#include <gcell/gc_job_desc.h>
-#include <gcell/gc_mbox.h>
-#include <gcell/gc_declare_proc.h>
-#include <gcell/spu/gc_jd_queue.h>
-#include <gcell/spu/gc_random.h>
-#include <gcell/spu/gc_delay.h>
-
-#include <string.h>
-#include <assert.h>
-#include <stdio.h>
-
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-//! round x down to p2 boundary (p2 must be a power-of-2)
-#define ROUND_DN(x, p2) ((x) & ~((p2)-1))
-
-//! round x up to p2 boundary (p2 must be a power-of-2)
-#define ROUND_UP(x, p2) (((x)+((p2)-1)) & ~((p2)-1))
-
-
-//#define OUT_MBOX_CHANNEL SPU_WrOutIntrMbox
-#define OUT_MBOX_CHANNEL SPU_WrOutMbox
-
-#define CHECK_QUEUE_ON_MSG 0 // define to 0 or 1
-#define USE_LLR_LOST_EVENT 0 // define to 0 or 1
-
-int gc_sys_tag; // tag for misc DMA operations
-static gc_spu_args_t spu_args;
-
-static struct gc_proc_def *gc_proc_def; // procedure entry points
-
-// ------------------------------------------------------------------------
-
-// state for DMA'ing arguments in and out
-
-static int get_tag; // 1 tag for job arg gets
-static int put_tags; // 2 tags for job arg puts
-
-static int pb_idx = 0; // current put buffer index (0 or 1)
-
-// bitmask (bit per put buffer): bit is set if DMA is started but not complete
-static int put_in_progress = 0;
-#define PBI_MASK(_pbi_) (1 << (_pbi_))
-
-// ------------------------------------------------------------------------
-
-// our working copy of the completion info
-static gc_comp_info_t comp_info = {
- .in_use = 1,
- .ncomplete = 0
-};
-
-static int ci_idx = 0; // index of current comp_info
-static int ci_tags; // two consecutive dma tags
-
-// ------------------------------------------------------------------------
-
-/*
- * Wait until EA copy of comp_info[idx].in_use is 0
- */
-static void
-wait_for_ppe_to_be_done_with_comp_info(int idx)
-{
- char _tmp[256];
- char *buf = (char *) ALIGN(_tmp, 128); // get cache-aligned buffer
- gc_comp_info_t *p = (gc_comp_info_t *) buf;
-
- assert(sizeof(gc_comp_info_t) == 128);
-
- do {
- mfc_get(buf, spu_args.comp_info[idx], 128, gc_sys_tag, 0, 0);
- mfc_write_tag_mask(1 << gc_sys_tag);
- mfc_read_tag_status_all();
- if (p->in_use == 0)
- return;
-
- gc_udelay(1);
-
- } while (1);
-}
-
-static void
-flush_completion_info(void)
-{
- // events: 0x3X
-
- static int total_complete = 0;
-
- if (comp_info.ncomplete == 0)
- return;
-
- // ensure that PPE is done with the buffer we're about to overwrite
- wait_for_ppe_to_be_done_with_comp_info(ci_idx);
-
- // dma the comp_info out to PPE
- int tag = ci_tags + ci_idx;
- mfc_put(&comp_info, spu_args.comp_info[ci_idx], sizeof(gc_comp_info_t), tag, 0, 0);
-
- // we need to wait for the completion info to finish, as well as
- // any EA argument puts.
-
- int tag_mask = 1 << tag; // the comp_info tag
- if (put_in_progress & PBI_MASK(0))
- tag_mask |= (1 << (put_tags + 0));
- if (put_in_progress & PBI_MASK(1))
- tag_mask |= (1 << (put_tags + 1));
-
- gc_log_write2(GCL_SS_SYS, 0x30, put_in_progress, tag_mask);
-
- mfc_write_tag_mask(tag_mask); // the tags we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
- put_in_progress = 0; // mark them all complete
-
- total_complete += comp_info.ncomplete;
- gc_log_write4(GCL_SS_SYS, 0x31,
- put_in_progress, ci_idx, comp_info.ncomplete, total_complete);
-
- // send PPE a message
- spu_writech(OUT_MBOX_CHANNEL, MK_MBOX_MSG(OP_JOBS_DONE, ci_idx));
-
- ci_idx ^= 0x1; // switch buffers
- comp_info.in_use = 1;
- comp_info.ncomplete = 0;
-}
-
-// ------------------------------------------------------------------------
-
-
-static unsigned int backoff; // current backoff value in clock cycles
-static unsigned int _backoff_start;
-static unsigned int _backoff_cap;
-
-/*
- * For 3.2 GHz SPE
- *
- * 10 1023 cycles 320 ns
- * 11 2047 cycle 640 ns
- * 12 4095 cycles 1.3 us
- * 13 8191 cycles 2.6 us
- * 14 16383 cycles 5.1 us
- * 15 32767 cycles 10.2 us
- * 16 20.4 us
- * 17 40.8 us
- * 18 81.9 us
- * 19 163.8 us
- * 20 327.7 us
- * 21 655.4 us
- */
-static unsigned char log2_backoff_start[16] = {
-// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-// -------------------------------------------------------------
-//12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 16
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
-};
-
-static unsigned char log2_backoff_cap[16] = {
-// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-// -------------------------------------------------------------
-//17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21
- 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16
-};
-
-static void
-backoff_init(void)
-{
- _backoff_cap = (1 << (log2_backoff_cap[(spu_args.nspus - 1) & 0xf])) - 1;
- _backoff_start = (1 << (log2_backoff_start[(spu_args.nspus - 1) & 0xf])) - 1;
-
- backoff = _backoff_start;
-}
-
-#if !CHECK_QUEUE_ON_MSG
-
-static void
-backoff_reset(void)
-{
- backoff = _backoff_start;
-}
-
-
-#define RANDOM_WEIGHT 0.2
-
-static void
-backoff_delay(void)
-{
- gc_cdelay(backoff);
-
- // capped exponential backoff
- backoff = ((backoff << 1) + 1);
- if (backoff > _backoff_cap)
- backoff = _backoff_cap;
-
- // plus some randomness
- float r = (RANDOM_WEIGHT * (2.0 * (gc_uniform_deviate() - 0.5)));
- backoff = backoff * (1.0 + r);
-}
-
-#endif // !CHECK_QUEUE_ON_MSG
-
-// ------------------------------------------------------------------------
-
-static inline unsigned int
-make_mask(int nbits)
-{
- return ~(~0 << nbits);
-}
-
-static unsigned int dc_work;
-static int dc_put_tag;
-static unsigned char *dc_ls_base;
-static gc_eaddr_t dc_ea_base;
-
-// divide and conquer
-static void
-d_and_c(unsigned int offset, unsigned int len)
-{
- unsigned int mask = make_mask(len) << offset;
- unsigned int t = mask & dc_work;
- if (t == 0) // nothing to do
- return;
- if (t == mask){ // got a match, generate dma
- mfc_put(dc_ls_base + offset, dc_ea_base + offset, len, dc_put_tag, 0, 0);
- }
- else { // bisect
- len >>= 1;
- d_and_c(offset, len);
- d_and_c(offset + len, len);
- }
-}
-
-// Handle the nasty case of a dma xfer that's less than 16 bytes long.
-// len is guaranteed to be in [1, 15]
-
-static void
-handle_slow_and_tedious_dma(gc_eaddr_t ea, unsigned char *ls,
- unsigned int len, int put_tag)
-{
- // Set up for divide and conquer
- unsigned int alignment = ((uintptr_t) ls) & 0x7;
- dc_work = make_mask(len) << alignment;
- dc_ls_base = (unsigned char *) ROUND_DN((uintptr_t) ls, 8);
- dc_ea_base = ROUND_DN(ea, (gc_eaddr_t) 8);
- dc_put_tag = put_tag;
-
- d_and_c( 0, 8);
- d_and_c( 8, 8);
- d_and_c(16, 8);
-}
-
-
-static void
-process_job(gc_eaddr_t jd_ea, gc_job_desc_t *jd)
-{
- // events: 0x2X
-
- jd->status = JS_OK; // assume success
-
- if (jd->proc_id >= spu_args.nproc_defs)
- jd->status = JS_UNKNOWN_PROC;
-
- else {
-
- if (jd->eaa.nargs == 0)
- (*gc_proc_def[jd->proc_id].proc)(&jd->input, &jd->output, &jd->eaa);
-
- else { // handle EA args that must be DMA'd in/out
-
- gc_job_ea_args_t *eaa = &jd->eaa;
-
- int NELMS =
- MAX(MAX_ARGS_EA,
- (GC_SPU_BUFSIZE + MFC_MAX_DMA_SIZE - 1) / MFC_MAX_DMA_SIZE);
-
- mfc_list_element_t dma_get_list[NELMS];
- //mfc_list_element_t dma_put_list[NELMS];
-
- memset(dma_get_list, 0, sizeof(dma_get_list));
- //memset(dma_put_list, 0, sizeof(dma_put_list));
-
- int gli = 0; // get list index
- //int pli = 0; // put list index
-
- unsigned char *get_base = _gci_getbuf[0];
- unsigned char *get_t = get_base;
- unsigned int total_get_dma_len = 0;
-
- unsigned char *put_base = _gci_putbuf[pb_idx];
- unsigned char *put_t = put_base;
- unsigned int total_put_alloc = 0;
- int put_tag = put_tags + pb_idx;
-
- // Do we have any "put" args? If so ensure that previous
- // dma from this buffer is complete
-
- gc_log_write2(GCL_SS_SYS, 0x24, put_in_progress, jd->sys.direction_union);
-
- if ((jd->sys.direction_union & GCJD_DMA_PUT)
- && (put_in_progress & PBI_MASK(pb_idx))){
-
- gc_log_write2(GCL_SS_SYS, 0x25, put_in_progress, 1 << put_tag);
-
- mfc_write_tag_mask(1 << put_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
- put_in_progress &= ~(PBI_MASK(pb_idx));
-
- gc_log_write1(GCL_SS_SYS, 0x26, put_in_progress);
- }
-
-
- // for now, all EA's must have the same high 32-bits
- gc_eaddr_t common_ea = eaa->arg[0].ea_addr;
-
-
- // assign LS addresses for buffers
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
-
- gc_eaddr_t ea_base = 0;
- unsigned char *ls_base;
- int offset;
- unsigned int dma_len;
-
- if (eaa->arg[i].direction == GCJD_DMA_GET){
- ea_base = ROUND_DN(eaa->arg[i].ea_addr, (gc_eaddr_t) CACHE_LINE_SIZE);
- offset = eaa->arg[i].ea_addr & (CACHE_LINE_SIZE-1);
- dma_len = ROUND_UP(eaa->arg[i].get_size + offset, CACHE_LINE_SIZE);
- total_get_dma_len += dma_len;
-
- if (total_get_dma_len > GC_SPU_BUFSIZE){
- jd->status = JS_ARGS_TOO_LONG;
- goto wrap_up;
- }
-
- ls_base = get_t;
- get_t += dma_len;
- eaa->arg[i].ls_addr = ls_base + offset;
-
- if (0){
- assert((mfc_ea2l(eaa->arg[i].ea_addr) & 0x7f) == ((intptr_t)eaa->arg[i].ls_addr & 0x7f));
- assert((ea_base & 0x7f) == 0);
- assert(((intptr_t)ls_base & 0x7f) == 0);
- assert((dma_len & 0x7f) == 0);
- assert((eaa->arg[i].get_size <= dma_len)
- && dma_len <= (eaa->arg[i].get_size + offset + CACHE_LINE_SIZE - 1));
- }
-
- // add to dma get list
- // FIXME (someday) the dma list is where the JS_BAD_EAH limitation comes from
-
- while (dma_len != 0){
- int n = MIN(dma_len, MFC_MAX_DMA_SIZE);
- dma_get_list[gli].size = n;
- dma_get_list[gli].eal = mfc_ea2l(ea_base);
- dma_len -= n;
- ea_base += n;
- gli++;
- }
- }
-
- else if (eaa->arg[i].direction == GCJD_DMA_PUT){
- //
- // This case is a trickier than the PUT case since we can't
- // write outside of the bounds of the user provided buffer.
- // We still align the buffers to 128-bytes for good performance
- // in the middle portion of the xfers.
- //
- ea_base = ROUND_DN(eaa->arg[i].ea_addr, (gc_eaddr_t) CACHE_LINE_SIZE);
- offset = eaa->arg[i].ea_addr & (CACHE_LINE_SIZE-1);
-
- uint32_t ls_alloc_len =
- ROUND_UP(eaa->arg[i].put_size + offset, CACHE_LINE_SIZE);
-
- total_put_alloc += ls_alloc_len;
-
- if (total_put_alloc > GC_SPU_BUFSIZE){
- jd->status = JS_ARGS_TOO_LONG;
- goto wrap_up;
- }
-
- ls_base = put_t;
- put_t += ls_alloc_len;
- eaa->arg[i].ls_addr = ls_base + offset;
-
- if (1){
- assert((mfc_ea2l(eaa->arg[i].ea_addr) & 0x7f)
- == ((intptr_t)eaa->arg[i].ls_addr & 0x7f));
- assert((ea_base & 0x7f) == 0);
- assert(((intptr_t)ls_base & 0x7f) == 0);
- }
- }
-
- else
- assert(0);
- }
-
- // fire off the dma to fetch the args and wait for it to complete
- mfc_getl(get_base, common_ea, dma_get_list, gli*sizeof(dma_get_list[0]), get_tag, 0, 0);
- mfc_write_tag_mask(1 << get_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- // do the work
- (*gc_proc_def[jd->proc_id].proc)(&jd->input, &jd->output, &jd->eaa);
-
-
- // Do we have any "put" args? If so copy them out
- if (jd->sys.direction_union & GCJD_DMA_PUT){
-
- // Do the copy out using single DMA xfers. The LS ranges
- // aren't generally contiguous.
-
- bool started_dma = false;
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
- if (eaa->arg[i].direction == GCJD_DMA_PUT && eaa->arg[i].put_size != 0){
-
- started_dma = true;
-
- gc_eaddr_t ea;
- unsigned char *ls;
- unsigned int len;
-
- ea = eaa->arg[i].ea_addr;
- ls = (unsigned char *) eaa->arg[i].ls_addr;
- len = eaa->arg[i].put_size;
-
- if (len < 16)
- handle_slow_and_tedious_dma(ea, ls, len, put_tag);
-
- else {
- if ((ea & 0xf) != 0){
-
- // printf("1: ea = 0x%x len = %5d\n", (int) ea, len);
-
- // handle the "pre-multiple-of-16" portion
- // do 1, 2, 4, or 8 byte xfers as required
-
- if (ea & 0x1){ // do a 1-byte xfer
- mfc_put(ls, ea, 1, put_tag, 0, 0);
- ea += 1;
- ls += 1;
- len -= 1;
- }
- if (ea & 0x2){ // do a 2-byte xfer
- mfc_put(ls, ea, 2, put_tag, 0, 0);
- ea += 2;
- ls += 2;
- len -= 2;
- }
- if (ea & 0x4){ // do a 4-byte xfer
- mfc_put(ls, ea, 4, put_tag, 0, 0);
- ea += 4;
- ls += 4;
- len -= 4;
- }
- if (ea & 0x8){ // do an 8-byte xfer
- mfc_put(ls, ea, 8, put_tag, 0, 0);
- ea += 8;
- ls += 8;
- len -= 8;
- }
- }
-
- if (1){
- // printf("2: ea = 0x%x len = %5d\n", (int) ea, len);
- assert((ea & 0xf) == 0);
- assert((((intptr_t) ls) & 0xf) == 0);
- }
-
- // handle the "multiple-of-16" portion
-
- int aligned_len = ROUND_DN(len, 16);
- len = len & (16 - 1);
-
- while (aligned_len != 0){
- int dma_len = MIN(aligned_len, MFC_MAX_DMA_SIZE);
- mfc_put(ls, ea, dma_len, put_tag, 0, 0);
- ea += dma_len;
- ls += dma_len;
- aligned_len -= dma_len;
- }
-
- if (1){
- // printf("3: ea = 0x%x len = %5d\n", (int)ea, len);
- assert((ea & 0xf) == 0);
- assert((((intptr_t) ls) & 0xf) == 0);
- }
-
- // handle "post-multiple-of-16" portion
-
- if (len != 0){
-
- if (len >= 8){ // do an 8-byte xfer
- mfc_put(ls, ea, 8, put_tag, 0, 0);
- ea += 8;
- ls += 8;
- len -= 8;
- }
- if (len >= 4){ // do a 4-byte xfer
- mfc_put(ls, ea, 4, put_tag, 0, 0);
- ea += 4;
- ls += 4;
- len -= 4;
- }
- if (len >= 2){ // do a 2-byte xfer
- mfc_put(ls, ea, 2, put_tag, 0, 0);
- ea += 2;
- ls += 2;
- len -= 2;
- }
- if (len >= 1){ // do a 1-byte xfer
- mfc_put(ls, ea, 1, put_tag, 0, 0);
- ea += 1;
- ls += 1;
- len -= 1;
- }
- if (1)
- assert(len == 0);
- }
- }
- }
- }
- if (started_dma){
- put_in_progress |= PBI_MASK(pb_idx); // note it's running
- gc_log_write2(GCL_SS_SYS, 0x27, put_in_progress, pb_idx);
- pb_idx ^= 1; // toggle current buffer
- }
- }
- }
- }
-
- wrap_up:; // semicolon creates null statement for C99 compliance
-
- // Copy job descriptor back out to EA.
- // (The dma will be waited on in flush_completion_info)
- int tag = ci_tags + ci_idx; // use the current completion tag
- mfc_put(jd, jd_ea, sizeof(*jd), tag, 0, 0);
-
- // Tell PPE we're done with the job.
- //
- // We queue these up until we run out of room, or until we can send
- // the info to the PPE w/o blocking. The blocking check is in
- // main_loop
-
- comp_info.job_id[comp_info.ncomplete++] = jd->sys.job_id;
-
- if (comp_info.ncomplete == GC_CI_NJOBS){
- gc_log_write0(GCL_SS_SYS, 0x28);
- flush_completion_info();
- }
-}
-
-static void
-main_loop(void)
-{
- // events: 0x1X
-
- static gc_job_desc_t jd; // static gets us proper alignment
- gc_eaddr_t jd_ea;
- int total_jobs = 0;
-
-#if (USE_LLR_LOST_EVENT)
- // setup events
- spu_writech(SPU_WrEventMask, MFC_LLR_LOST_EVENT);
-
- // prime the pump
- while (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd))
- process_job(jd_ea, &jd);
- // we're now holding a lock-line reservation
-#endif
-
- while (1){
-
-#if !CHECK_QUEUE_ON_MSG
-#if (USE_LLR_LOST_EVENT)
-
- if (unlikely(spu_readchcnt(SPU_RdEventStat))){
- //
- // execute standard event handling prologue
- //
- int status = spu_readch(SPU_RdEventStat);
- int mask = spu_readch(SPU_RdEventMask);
- spu_writech(SPU_WrEventMask, mask & ~status); // disable active events
- spu_writech(SPU_WrEventAck, status); // ack active events
-
- // execute per-event actions
-
- if (status & MFC_LLR_LOST_EVENT){
- //
- // We've lost a line reservation. This is most likely caused
- // by somebody doing something to the queue. Go look and see
- // if there's anything for us.
- //
- while (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd) == GCQ_OK)
- process_job(jd_ea, &jd);
- }
-
- //
- // execute standard event handling epilogue
- //
- spu_writech(SPU_WrEventMask, mask); // restore event mask
- }
-
-#else
-
- // try to get a job from the job queue
- if (gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd) == GCQ_OK){
- total_jobs++;
- gc_log_write2(GCL_SS_SYS, 0x10, jd.sys.job_id, total_jobs);
-
- process_job(jd_ea, &jd);
-
- gc_log_write2(GCL_SS_SYS, 0x11, jd.sys.job_id, total_jobs);
- backoff_reset();
- }
- else
- backoff_delay();
-
-#endif
-#endif
-
- // any msgs for us?
-
- if (unlikely(spu_readchcnt(SPU_RdInMbox))){
- int msg = spu_readch(SPU_RdInMbox);
- // printf("spu[%d] mbox_msg: 0x%08x\n", spu_args.spu_idx, msg);
-#if CHECK_QUEUE_ON_MSG
- if (MBOX_MSG_OP(msg) == OP_CHECK_QUEUE){
-
- while (1){
- //int delay = (int)(3200.0 * gc_uniform_deviate()); // uniformly in [0, 1.0us]
- //gc_cdelay(delay);
-
- gc_dequeue_status_t s =
- gc_jd_queue_dequeue(spu_args.queue, &jd_ea, ci_tags + ci_idx, &jd);
-
- if (s == GCQ_OK){
- total_jobs++;
- gc_log_write2(GCL_SS_SYS, 0x10, jd.sys.job_id, total_jobs);
-
- process_job(jd_ea, &jd);
-
- gc_log_write2(GCL_SS_SYS, 0x11, jd.sys.job_id, total_jobs);
- }
- else if (s == GCQ_EMPTY){
- break;
- }
- else { // GCQ_LOCKED -- keep trying
- }
- }
- }
- else
-#endif
- if (MBOX_MSG_OP(msg) == OP_EXIT){
- flush_completion_info();
- return;
- }
- else if (MBOX_MSG_OP(msg) == OP_GET_SPU_BUFSIZE){
- spu_writech(SPU_WrOutIntrMbox, MK_MBOX_MSG(OP_SPU_BUFSIZE, GC_SPU_BUFSIZE_BASE));
- }
- }
-
- // If we've got job completion info for the PPE and we can send a
- // message without blocking, do it.
-
- if (comp_info.ncomplete != 0 && spu_readchcnt(OUT_MBOX_CHANNEL) != 0){
- gc_log_write0(GCL_SS_SYS, 0x12);
- flush_completion_info();
- }
- }
-}
-
-
-int
-main(unsigned long long spe_id __attribute__((unused)),
- unsigned long long argp,
- unsigned long long envp __attribute__((unused)))
-{
- gc_sys_tag = mfc_tag_reserve(); // allocate a tag for our misc DMA operations
- get_tag = mfc_tag_reserve();
- ci_tags = mfc_multi_tag_reserve(2);
- put_tags = mfc_multi_tag_reserve(2);
-
- // dma the args in
- mfc_get(&spu_args, argp, sizeof(spu_args), gc_sys_tag, 0, 0);
- mfc_write_tag_mask(1 << gc_sys_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- // initialize pointer to procedure entry table
- gc_proc_def = (gc_proc_def_t *) spu_args.proc_def_ls_addr;
-
- gc_set_seed(spu_args.spu_idx);
-
- // initialize logging
- _gc_log_init(spu_args.log);
-
- backoff_init(); // initialize backoff parameters
-
- main_loop();
- return 0;
-}
diff --git a/gcell/lib/runtime/spu/gc_random.c b/gcell/lib/runtime/spu/gc_random.c
deleted file mode 100644
index ae2fde875..000000000
--- a/gcell/lib/runtime/spu/gc_random.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <gcell/spu/gc_random.h>
-
-static int last_val = 0;
-
-# define M 259200 // values from Numerical Recipes in C, 1988
-# define A 7141
-# define C 54773
-
-void
-gc_set_seed(int seed)
-{
- last_val = ((unsigned int) seed) % M;
-}
-
-/*
- * Return a uniformly distributed value in the range [0, 1.0)
- * (Linear congruential generator. YMMV. Caveat emptor.)
- */
-float
-gc_uniform_deviate(void)
-{
- last_val = (last_val * A + C) % M;
- return (float) last_val * (1.0f / (float) M);
-}
diff --git a/gcell/lib/runtime/spu/gc_spu_config.h b/gcell/lib/runtime/spu/gc_spu_config.h
deleted file mode 100644
index 6320e6dbe..000000000
--- a/gcell/lib/runtime/spu/gc_spu_config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- c -*- */
-/*
- * Copyright 2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_GCELL_GC_SPU_CONFIG_H
-#define INCLUDED_GCELL_GC_SPU_CONFIG_H
-
-#include <gcell/gc_job_desc.h>
-
-#define CACHE_LINE_SIZE 128 // in bytes
-
-#if 1
-# define GC_SPU_BUFSIZE_BASE (40 * 1024) // must be multiple of CACHE_LINE_SIZE
-#else
-# define GC_SPU_BUFSIZE_BASE (20 * 1024) // must be multiple of CACHE_LINE_SIZE
-#endif
-
-#define GC_SPU_BUFSIZE (GC_SPU_BUFSIZE_BASE + MAX_ARGS_EA * CACHE_LINE_SIZE)
-
-#define NGETBUFS 1 // gets are single buffered
-#define NPUTBUFS 2 // puts are double buffered
-
-#endif /* INCLUDED_GCELL_GC_SPU_CONFIG_H */
diff --git a/gcell/lib/runtime/spu/gc_spu_jd_queue.c b/gcell/lib/runtime/spu/gc_spu_jd_queue.c
deleted file mode 100644
index 91bb5bc7e..000000000
--- a/gcell/lib/runtime/spu/gc_spu_jd_queue.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007,2008,2009 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/spu/gc_jd_queue.h>
-#include <gcell/spu/gc_delay.h>
-#include <gcell/spu/gc_random.h>
-#include "mutex_lock.h"
-#include "mutex_unlock.h"
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-extern int gc_sys_tag;
-
-// keep track of stats
-int jdq_ok;
-int jdq_empty;
-int jdq_locked;
-
-
-#define INITIAL_BACKOFF 32.0
-#define MAX_BACKOFF 8192.0 /* 2.6us */
-#define RANDOM_WEIGHT 0.2
-
-static float
-next_backoff(float backoff)
-{
- // exponential with random
- float t = backoff * 2.0;
- if (t > MAX_BACKOFF)
- t = MAX_BACKOFF;
-
- float r = (RANDOM_WEIGHT * (2.0 * (gc_uniform_deviate() - 0.5)));
- t = t * (1.0 + r);
-
- return t;
-}
-
-gc_dequeue_status_t
-gc_jd_queue_dequeue(gc_eaddr_t q, gc_eaddr_t *item_ea,
- int jd_tag, gc_job_desc_t *item)
-{
- int status;
- char _tmp[256];
- gc_jd_queue_t *local_q =
- (gc_jd_queue_t *) ALIGN(_tmp, 128); // get cache-aligned buffer
-
- float backoff = next_backoff(INITIAL_BACKOFF);
-
- do {
- // Copy the queue structure in and get a lock line reservation.
- // (The structure is 128-byte aligned and completely fills a cache-line)
-
- mfc_getllar(local_q, q, 0, 0);
- spu_readch(MFC_RdAtomicStat);
-
- if (local_q->mutex != 0){ // somebody else has it locked
- jdq_locked++;
- return GCQ_LOCKED;
- }
-
- if (local_q->head == 0){ // the queue is empty
- jdq_empty++;
- return GCQ_EMPTY;
- }
-
- // Try to acquire the lock
-
- local_q->mutex = 1;
- mfc_putllc(local_q, q, 0, 0);
- status = spu_readch(MFC_RdAtomicStat);
-
- if (status != 0){
- gc_cdelay((int) backoff);
- backoff = next_backoff(backoff);
- }
-
- } while (status != 0);
-
- // we're now holding the lock
-
- // copy in job descriptor at head of queue
- *item_ea = local_q->head;
-
- // We must use the fence with the jd_tag to ensure that any
- // previously initiated put of a job desc is locally ordered before
- // the get of the new one.
- mfc_getf(item, local_q->head, sizeof(gc_job_desc_t), jd_tag, 0, 0);
- mfc_write_tag_mask(1 << jd_tag); // the tag we're interested in
- mfc_read_tag_status_all(); // wait for DMA to complete
-
- local_q->head = item->sys.next;
- item->sys.next = 0;
- if (local_q->head == 0) // now empty?
- local_q->tail = 0;
-
- // Copy the queue struct back out and unlock the mutex in one fell swoop.
- // We use the unconditional put since it's faster and we own the lock.
-
- local_q->mutex = 0;
- mfc_putlluc(local_q, q, 0, 0);
- spu_readch(MFC_RdAtomicStat);
-
- jdq_ok++;
- return GCQ_OK;
-}
diff --git a/gcell/lib/runtime/spu/gcell_runtime_qa.c b/gcell/lib/runtime/spu/gcell_runtime_qa.c
deleted file mode 100644
index 47a4b5b5b..000000000
--- a/gcell/lib/runtime/spu/gcell_runtime_qa.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <gcell/gc_declare_proc.h>
-#include <gcell/spu/gc_delay.h>
-#include <string.h>
-
-
-static void
-qa_nop(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output _UNUSED,
- const gc_job_ea_args_t *eaa _UNUSED)
-{
-}
-
-GC_DECLARE_PROC(qa_nop, "qa_nop");
-
-static int
-sum_shorts(short *p, int nshorts)
-{
- int total = 0;
- for (int i = 0; i < nshorts; i++)
- total += p[i];
-
- return total;
-}
-
-static void
-qa_sum_shorts(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output,
- const gc_job_ea_args_t *eaa)
-{
- for (unsigned int i = 0; i < eaa->nargs; i++){
- short *p = eaa->arg[i].ls_addr;
- int n = eaa->arg[i].get_size / sizeof(short);
- output->arg[i].s32 = sum_shorts(p, n);
- //printf("qa_sum_shorts(%p, %d) = %d\n", p, n, output->arg[i].s32);
- }
-}
-
-GC_DECLARE_PROC(qa_sum_shorts, "qa_sum_shorts");
-
-static void
-write_seq(unsigned char *p, int nbytes, int counter)
-{
- for (int i = 0; i < nbytes; i++)
- p[i] = counter++;
-}
-
-static void
-qa_put_seq(const gc_job_direct_args_t *input,
- gc_job_direct_args_t *output _UNUSED,
- const gc_job_ea_args_t *eaa)
-{
- int counter = input->arg[0].s32;
-
- for (unsigned int i = 0; i < eaa->nargs; i++){
- unsigned char *p = eaa->arg[i].ls_addr;
- int n = eaa->arg[i].put_size;
- write_seq(p, n, counter);
- counter += n;
- }
-}
-
-GC_DECLARE_PROC(qa_put_seq, "qa_put_seq");
-
-static void
-qa_copy(const gc_job_direct_args_t *input _UNUSED,
- gc_job_direct_args_t *output,
- const gc_job_ea_args_t *eaa)
-{
- if (eaa->nargs != 2
- || eaa->arg[0].direction != GCJD_DMA_PUT
- || eaa->arg[1].direction != GCJD_DMA_GET){
- output->arg[0].s32 = -1;
- return;
- }
-
- output->arg[0].s32 = 0;
- unsigned n = eaa->arg[0].put_size;
- if (eaa->arg[1].get_size < n)
- n = eaa->arg[1].get_size;
-
- memcpy(eaa->arg[0].ls_addr, eaa->arg[1].ls_addr, n);
-}
-
-GC_DECLARE_PROC(qa_copy, "qa_copy");
diff --git a/gcell/lib/runtime/spu/spu_buffers.c b/gcell/lib/runtime/spu/spu_buffers.c
deleted file mode 100644
index 29ae99d9f..000000000
--- a/gcell/lib/runtime/spu/spu_buffers.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "spu_buffers.h"
-#include <gcell/compiler.h>
-
-static unsigned char _getbuf[NGETBUFS][GC_SPU_BUFSIZE] _AL128;
-static unsigned char _putbuf[NPUTBUFS][GC_SPU_BUFSIZE] _AL128;
-
-unsigned char *_gci_getbuf[NGETBUFS] = {
- _getbuf[0]
-};
-
-unsigned char *_gci_putbuf[NPUTBUFS] = {
- _putbuf[0],
- _putbuf[1]
-};
diff --git a/gcell/lib/runtime/spu/spu_buffers.h b/gcell/lib/runtime/spu/spu_buffers.h
deleted file mode 100644
index 24811dc38..000000000
--- a/gcell/lib/runtime/spu/spu_buffers.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2008 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_SPU_BUFFERS_H
-#define INCLUDED_SPU_BUFFERS_H
-
-#include "gc_spu_config.h"
-
-//! pointer to input buffer
-extern unsigned char *_gci_getbuf[NGETBUFS];
-
-//! pointers to output buffers
-extern unsigned char *_gci_putbuf[NPUTBUFS];
-
-#endif /* INCLUDED_SPU_BUFFERS_H */