aboutsummaryrefslogtreecommitdiff
path: root/src/core/dsp/driver_hawking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/dsp/driver_hawking.cpp')
-rw-r--r--src/core/dsp/driver_hawking.cpp451
1 files changed, 451 insertions, 0 deletions
diff --git a/src/core/dsp/driver_hawking.cpp b/src/core/dsp/driver_hawking.cpp
new file mode 100644
index 0000000..7cb2857
--- /dev/null
+++ b/src/core/dsp/driver_hawking.cpp
@@ -0,0 +1,451 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#include "driver.h"
+#include <deque>
+#include <iostream>
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <sys/stat.h>
+#include <string>
+#include <bfd.h>
+
+extern "C"
+{
+ #include "mpmclient.h"
+};
+
+
+#define ERR(status, msg) if (status) { printf("ERROR: %s\n", msg); exit(-1); }
+#define BOOT_ENTRY_LOCATION_ADDR 0x87FFFC
+#define BOOT_MAGIC_ADDR(core) (0x10000000 | (core << 24) | 0x87FFFC)
+
+Driver* Driver::pInstance = 0;
+
+/******************************************************************************
+* Thread safe instance function for singleton behavior
+******************************************************************************/
+Driver* Driver::instance ()
+{
+ static Mutex Driver_instance_mutex;
+ Driver* tmp = pInstance;
+
+ __sync_synchronize();
+
+ if (tmp == 0)
+ {
+ ScopedLock lck(Driver_instance_mutex);
+
+ tmp = pInstance;
+ if (tmp == 0)
+ {
+ tmp = new Driver;
+ __sync_synchronize();
+ pInstance = tmp;
+ }
+ }
+ return tmp;
+}
+
+/******************************************************************************
+* Convert pci data into a recognizable board name for a device
+******************************************************************************/
+const char *get_board(unsigned switch_device)
+{
+ switch (switch_device)
+ {
+ case 0x8624: return "dspc8681";
+ case 0x8748: return "dspc8682";
+ default : ERR(1, "Unsupported device"); return "unknown";
+ }
+}
+
+#define TOTAL_NUM_CORES_PER_CHIP 8
+
+/******************************************************************************
+* wait_for_ready
+******************************************************************************/
+bool Driver::wait_for_ready(int chip) { return true; }
+
+static void report_core_state(const char *curr_core)
+{
+#if 0
+ char state[50];
+ int ret;
+ mpm_slave_state_e core_state;
+
+ ret = mpm_state(curr_core, &core_state);
+ if ( ret < 0)
+ printf("state query failed, %s\n", curr_core);
+
+ switch (core_state)
+ {
+ case mpm_slave_state_idle: sprintf(state, "idle"); break;
+ case mpm_slave_state_loaded: sprintf(state, "loaded"); break;
+ case mpm_slave_state_running: sprintf(state, "running"); break;
+ case mpm_slave_state_crashed: sprintf(state, "crashed"); break;
+ case mpm_slave_state_error: sprintf(state, "in error"); break;
+
+ default: sprintf(state, "in undefined state"); break;
+ }
+
+ printf("DSP core state: %s is %s\n", curr_core, state);
+#endif
+}
+
+void *Driver::reset_and_load(int chip)
+{
+ int ret;
+ int error_code = 0;
+ int error_code_msg[50];
+ char curr_core[10];
+
+ std::string get_ocl_dsp();
+ std::string monitor = get_ocl_dsp() + "/dsp.out";
+
+ for (int core=0; core< TOTAL_NUM_CORES_PER_CHIP; core++)
+ {
+ snprintf(curr_core, 5, "dsp%d", core);
+
+ ret = mpm_reset(curr_core, &error_code);
+ if ( ret < 0)
+ printf("reset failed, core %d (retval: %d, error: %d)\n",
+ core, ret, error_code);
+// JKN Update ERR to handle error_code
+ ERR (ret, "DSP out of reset failed");
+
+ report_core_state(curr_core);
+ }
+
+ /*-------------------------------------------------------------------------
+ * Load monitor on the devices
+ *------------------------------------------------------------------------*/
+ for (int core=0; core< TOTAL_NUM_CORES_PER_CHIP; core++)
+ {
+ snprintf(curr_core, 5,"dsp%d", core);
+ ret = mpm_load(curr_core, const_cast<char*>(monitor.c_str()),
+ &error_code);
+ if ( ret < 0)
+ printf("load failed, core %d (retval: %d, error: %d)\n",
+ core, ret, error_code);
+ ERR(ret, "Download image failed");
+
+ report_core_state(curr_core);
+ }
+
+ /*-------------------------------------------------------------------------
+ * Run monitor on the devices
+ *------------------------------------------------------------------------*/
+ for (int core=0; core< TOTAL_NUM_CORES_PER_CHIP; core++)
+ {
+ snprintf(curr_core, 5,"dsp%d", core);
+ ret = mpm_run(curr_core, &error_code);
+ if ( ret < 0)
+ printf("run failed, core %d (retval: %d, error: %d)\n",
+ core, ret, error_code);
+ ERR(ret, "DSP run failed");
+
+ report_core_state(curr_core);
+ }
+
+ bfd *dsp_bfd = bfd_openr(monitor.c_str(), NULL);
+ char** matching;
+ char *ptr;
+
+ if(dsp_bfd == NULL)
+ {
+ printf("\nERROR:driver: %s Error Open image %s\n",
+ bfd_errmsg(bfd_get_error()), monitor.c_str());
+ exit(-1);
+ }
+ /* Check format with matching */
+ if (!bfd_check_format_matches (dsp_bfd, bfd_object, &matching))
+ {
+ fprintf(stderr, "\nERROR:driver %s: %s\n", monitor.c_str(),
+ bfd_errmsg(bfd_get_error()));
+ if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+ {
+ for (ptr = *matching; ptr != NULL; ptr++)
+ {
+ printf("%s: \n", ptr);
+ exit(-1);
+ }
+ free (matching);
+ }
+ }
+
+ return (void *)dsp_bfd;
+}
+
+/******************************************************************************
+* Driver::open
+******************************************************************************/
+int32_t Driver::open()
+{
+ Lock lock(this);
+
+ pNum_dsps = 1;
+
+ return 0;
+}
+
+/******************************************************************************
+* Driver::close()
+******************************************************************************/
+int32_t Driver::close()
+{
+ Lock lock(this);
+
+ while (!pShmem_areas.empty()) delete pShmem_areas.back(), pShmem_areas.pop_back();
+
+ cmem_exit();
+ return 0;
+}
+
+void Driver::cmem_init(DSPDevicePtr64 *addr1, uint64_t *size1,
+ DSPDevicePtr *addr2, uint32_t *size2,
+ DSPDevicePtr64 *addr3, uint64_t *size3)
+{
+ shmem_cmem_persistent::cmem_init(addr1, size1, addr2, size2, addr3, size3);
+}
+
+void Driver::cmem_exit()
+{
+ shmem_cmem_persistent::cmem_exit();
+}
+
+DSPDevicePtr64 Driver::cmem_ondemand_malloc(uint64_t size)
+{
+ return shmem_cmem_ondemand::cmem_malloc(size);
+}
+
+void Driver::cmem_ondemand_free(DSPDevicePtr64 addr)
+{
+ shmem_cmem_ondemand::cmem_free(addr);
+}
+
+/******************************************************************************
+* Driver::split_ddr_heap: partition DDR to persistent mapping part (heap1)
+* and on demand mapping part (heap2)
+******************************************************************************/
+void Driver::split_ddr_memory(DSPDevicePtr64 addr, uint64_t size,
+ DSPDevicePtr64& addr1, uint64_t& size1,
+ DSPDevicePtr64& addr2, uint64_t& size2,
+ uint64_t& size3)
+{
+ addr1 = addr;
+ size1 = size;
+ addr2 = 0;
+ size2 = 0;
+
+
+ // split ddr memory 1 into two chunks
+ if (getenv("TI_OCL_DSP_NOMAP") != NULL)
+ {
+ size3 = 0;
+ }
+ else if (addr + size > ALL_PERSISTENT_MAX_DSP_ADDR ||
+ (size3 > 0 && addr + size > MPAX_USER_MAPPED_DSP_ADDR))
+ {
+ size2 = addr + size - MPAX_USER_MAPPED_DSP_ADDR;
+ size1 = size - size2;
+ addr2 = addr + size1;
+ }
+
+ // translate first chunk to using 32-bit aliased physical addresses
+ if (addr > DSP_36BIT_ADDR)
+ {
+ addr1 = addr + 0xA0000000 - 0x820000000ULL;
+ /*---------------------------------------------------------------------
+ * if the ddr size is greater than we can currently support, limit it
+ *--------------------------------------------------------------------*/
+ //const int ddr_size_limit = (1.5 * 1024*1024*1024) - (48 *1024*1024);
+ const uint64_t ddr_size_limit = ALL_PERSISTENT_MAX_DSP_ADDR - addr;
+ if (size1 > ddr_size_limit)
+ size1 = ddr_size_limit;
+ }
+}
+
+void Driver::shmem_configure(DSPDevicePtr64 addr, uint64_t size, int cmem_block)
+{
+ if (size <= 0) return;
+
+ shmem *area;
+ if (addr >= MPAX_USER_MAPPED_DSP_ADDR)
+ area = new shmem_cmem_ondemand();
+ else if (cmem_block >= 0)
+ area = new shmem_cmem_persistent(cmem_block);
+ else
+ area = new shmem_persistent();
+
+ area->configure(addr, size);
+ pShmem_areas.push_back(area);
+}
+
+/******************************************************************************
+* Driver::get_memory_region
+******************************************************************************/
+shmem* Driver::get_memory_region(DSPDevicePtr64 addr)
+{
+
+ for (int i = 0; i < pShmem_areas.size(); ++i)
+ {
+ uint64_t end_exclusive = (uint64_t)pShmem_areas[i]->start() +
+ pShmem_areas[i]->size();
+
+ if (addr >= pShmem_areas[i]->start() && addr < end_exclusive)
+ return pShmem_areas[i];
+ }
+
+ printf("Illegal memory region: addr = 0x%llx\n", addr);
+ exit(-1);
+}
+
+
+/******************************************************************************
+* Driver::write
+******************************************************************************/
+int32_t Driver::write(int32_t dsp_id, DSPDevicePtr64 addr, uint8_t *buf,
+ uint32_t size)
+{
+ int core;
+ /*-------------------------------------------------------------------------
+ * if the write is to L2, then write for each core
+ *------------------------------------------------------------------------*/
+ if ((addr >> 20) == 0x008)
+ for (core=0; core< TOTAL_NUM_CORES_PER_CHIP; core++)
+ write_core(dsp_id, ((0x10 + core) << 24) + addr, buf, size);
+ else write_core(dsp_id, addr, buf, size);
+}
+
+/******************************************************************************
+* Driver::write_core
+******************************************************************************/
+int32_t Driver::write_core(int32_t dsp_id, DSPDevicePtr64 addr, uint8_t *buf,
+ uint32_t size)
+{
+ Lock lock(this);
+
+ shmem* region = get_memory_region(addr);
+ void* dst_host_addr = region->map(addr, size, false);
+ if (dst_host_addr) memcpy((char*)dst_host_addr, buf, size);
+ else ERR(1, "Unable to map dsp addr for write");
+ region->unmap(dst_host_addr, size, true);
+
+ return 0;
+}
+
+void* Driver::map(DSPDevicePtr64 addr, uint32_t sz, bool is_read)
+{
+ Lock lock(this);
+ shmem* region = get_memory_region(addr);
+ void* host_addr = region->map(addr, sz, is_read);
+ if (host_addr == NULL) ERR(1, "Unable to map a dsp address");
+ return host_addr;
+}
+
+int32_t Driver::unmap(void *host_addr, DSPDevicePtr64 buf_addr, uint32_t sz,
+ bool is_write)
+{
+ Lock lock(this);
+ shmem* region = get_memory_region(buf_addr);
+ region->unmap(host_addr, sz, is_write);
+ return 0;
+}
+
+/******************************************************************************
+* Driver::read
+******************************************************************************/
+int32_t Driver::read(int32_t dsp_id, DSPDevicePtr64 addr, uint8_t *buf,
+ uint32_t size)
+{
+ Lock lock(this);
+
+ shmem* region = get_memory_region(addr);
+ void* dst_host_addr = region->map(addr, size, true);
+ if (dst_host_addr) memcpy(buf, (char*)dst_host_addr, size);
+ else ERR(1, "Unable to map dsp addr for read");
+ region->unmap(dst_host_addr, size, false);
+
+ return 0;
+}
+
+/******************************************************************************
+* Driver::free_image_handle
+******************************************************************************/
+void Driver::free_image_handle(void *handle)
+{
+ bfd_close((bfd*)handle);
+}
+
+/******************************************************************************
+* Driver::get_symbol
+******************************************************************************/
+DSPDevicePtr Driver::get_symbol(void* image_handle, const char *name)
+{
+ DSPDevicePtr addr;
+ bfd* dsp_bfd;
+ uint32_t nsyms, nsize;
+ asymbol ** symtab;
+ symbol_info syminfo;
+ int i;
+
+ if (!image_handle)
+ {
+ std::cout << "ERROR: Failed to get image handle" << std::endl;
+ exit(-1);
+ }
+
+ dsp_bfd = (bfd *)image_handle;
+
+ /*-------------------------------------------------------------------------
+ * Find boot address and address of mpi_rank.
+ *------------------------------------------------------------------------*/
+ nsize = bfd_get_symtab_upper_bound (dsp_bfd);
+ if ((symtab = (asymbol**)malloc(nsize)) == NULL)
+ {
+ std::cout << "ERROR: Failed to malloc memory in get_symbol" << std::endl;
+ exit(-1);
+ }
+
+ nsyms = bfd_canonicalize_symtab(dsp_bfd, symtab);
+
+ for (i = 0; i < nsyms; i++)
+ if (strcmp(symtab[i]->name, name) == 0)
+ {
+ bfd_symbol_info(symtab[i], &syminfo);
+ DSPDevicePtr addr = syminfo.value;
+ free(symtab);
+
+ return addr;
+ }
+
+ free(symtab);
+ std::cout << "ERROR: Get symbol failed" << std::endl;
+ exit(-1);
+}