summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/host_buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/lib/host_buffer.cc')
-rw-r--r--gnuradio-runtime/lib/host_buffer.cc255
1 files changed, 255 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/host_buffer.cc b/gnuradio-runtime/lib/host_buffer.cc
new file mode 100644
index 0000000000..6e1a1d1003
--- /dev/null
+++ b/gnuradio-runtime/lib/host_buffer.cc
@@ -0,0 +1,255 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2021 BlackLynx Inc..
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <cstring>
+#include <sstream>
+#include <stdexcept>
+
+#include <gnuradio/block.h>
+#include <gnuradio/host_buffer.h>
+
+namespace gr {
+
+buffer_type host_buffer::type(buftype_HOST_BUFFER{});
+
+void* host_buffer::device_memcpy(void* dest, const void* src, std::size_t count)
+{
+ // There is no spoon...er... device so fake it out using regular memcpy
+ return std::memcpy(dest, src, count);
+}
+
+void* host_buffer::device_memmove(void* dest, const void* src, std::size_t count)
+{
+ // There is no spoon...er... device so fake it out using regular memmmove
+ return std::memmove(dest, src, count);
+}
+
+
+host_buffer::host_buffer(int nitems,
+ size_t sizeof_item,
+ uint64_t downstream_lcm_nitems,
+ uint32_t downstream_max_out_mult,
+ block_sptr link,
+ block_sptr buf_owner)
+ : buffer_single_mapped(nitems,
+ sizeof_item,
+ downstream_lcm_nitems,
+ downstream_max_out_mult,
+ link,
+ buf_owner),
+ d_device_base(nullptr)
+{
+ gr::configure_default_loggers(d_logger, d_debug_logger, "host_buffer");
+ if (!allocate_buffer(nitems))
+ throw std::bad_alloc();
+}
+
+host_buffer::~host_buffer() {}
+
+void host_buffer::post_work(int nitems)
+{
+#ifdef BUFFER_DEBUG
+ std::ostringstream msg;
+ msg << "[" << this << "] "
+ << "host_buffer [" << d_context << "] -- post_work: " << nitems;
+ GR_LOG_DEBUG(d_logger, msg.str());
+#endif
+
+ if (nitems <= 0) {
+ return;
+ }
+
+ // NOTE: when this function is called the write pointer has not yet been
+ // advanced so it can be used directly as the source ptr
+ switch (d_context) {
+ case buffer_context::HOST_TO_DEVICE: {
+ // Copy data from host buffer to device buffer
+ void* dest_ptr = &d_device_base[d_write_index * d_sizeof_item];
+ device_memcpy(dest_ptr, write_pointer(), nitems * d_sizeof_item);
+ } break;
+
+ case buffer_context::DEVICE_TO_HOST: {
+ // Copy data from device buffer to host buffer
+ void* dest_ptr = &d_base[d_write_index * d_sizeof_item];
+ device_memcpy(dest_ptr, write_pointer(), nitems * d_sizeof_item);
+ } break;
+
+ case buffer_context::DEVICE_TO_DEVICE:
+ // No op
+ break;
+
+ default:
+ std::ostringstream msg;
+ msg << "Unexpected context for host_buffer: " << d_context;
+ GR_LOG_ERROR(d_logger, msg.str());
+ throw std::runtime_error(msg.str());
+ }
+}
+
+bool host_buffer::do_allocate_buffer(size_t final_nitems, size_t sizeof_item)
+{
+#ifdef BUFFER_DEBUG
+ {
+ std::ostringstream msg;
+ msg << "[" << this << "] "
+ << "host_buffer constructor -- nitems: " << final_nitems;
+ GR_LOG_DEBUG(d_logger, msg.str());
+ }
+#endif
+
+ // This is the host buffer
+ d_buffer.reset(new char[final_nitems * sizeof_item]());
+ d_base = d_buffer.get();
+
+ // This is the simulated device buffer
+ d_device_buf.reset(new char[final_nitems * sizeof_item]());
+ d_device_base = d_device_buf.get();
+
+ return true;
+}
+
+void* host_buffer::write_pointer()
+{
+ void* ptr = nullptr;
+ switch (d_context) {
+ case buffer_context::HOST_TO_DEVICE:
+ // Write into host buffer
+ ptr = &d_base[d_write_index * d_sizeof_item];
+ break;
+
+ case buffer_context::DEVICE_TO_HOST:
+ case buffer_context::DEVICE_TO_DEVICE:
+ // Write into "device" buffer
+ ptr = &d_device_base[d_write_index * d_sizeof_item];
+ break;
+
+ default:
+ std::ostringstream msg;
+ msg << "Unexpected context for host_buffer: " << d_context;
+ GR_LOG_ERROR(d_logger, msg.str());
+ throw std::runtime_error(msg.str());
+ }
+
+ return ptr;
+}
+
+const void* host_buffer::_read_pointer(unsigned int read_index)
+{
+ void* ptr = nullptr;
+ switch (d_context) {
+ case buffer_context::HOST_TO_DEVICE:
+ case buffer_context::DEVICE_TO_DEVICE:
+ // Read from "device" buffer
+ ptr = &d_device_base[read_index * d_sizeof_item];
+ break;
+
+ case buffer_context::DEVICE_TO_HOST:
+ // Read from host buffer
+ ptr = &d_base[read_index * d_sizeof_item];
+ break;
+
+ default:
+ std::ostringstream msg;
+ msg << "Unexpected context for host_buffer: " << d_context;
+ GR_LOG_ERROR(d_logger, msg.str());
+ throw std::runtime_error(msg.str());
+ }
+
+ return ptr;
+}
+
+bool host_buffer::input_blocked_callback(int items_required,
+ int items_avail,
+ unsigned read_index)
+{
+#ifdef BUFFER_DEBUG
+ std::ostringstream msg;
+ msg << "[" << this << "] "
+ << "host_buffer [" << d_context << "] -- input_blocked_callback";
+ GR_LOG_DEBUG(d_logger, msg.str());
+#endif
+
+ bool rc = false;
+ switch (d_context) {
+ case buffer_context::HOST_TO_DEVICE:
+ case buffer_context::DEVICE_TO_DEVICE:
+ // Adjust "device" buffer
+ rc = input_blocked_callback_logic(items_required,
+ items_avail,
+ read_index,
+ d_device_base,
+ host_buffer::device_memcpy,
+ host_buffer::device_memmove);
+ break;
+
+ case buffer_context::DEVICE_TO_HOST:
+ case buffer_context::HOST_TO_HOST:
+ // Adjust host buffer
+ rc = input_blocked_callback_logic(
+ items_required, items_avail, read_index, d_base, std::memcpy, std::memmove);
+ break;
+
+ default:
+ std::ostringstream msg;
+ msg << "Unexpected context for host_buffer: " << d_context;
+ GR_LOG_ERROR(d_logger, msg.str());
+ throw std::runtime_error(msg.str());
+ }
+
+ return rc;
+}
+
+bool host_buffer::output_blocked_callback(int output_multiple, bool force)
+{
+#ifdef BUFFER_DEBUG
+ std::ostringstream msg;
+ msg << "[" << this << "] "
+ << "host_buffer [" << d_context << "] -- output_blocked_callback";
+ GR_LOG_DEBUG(d_logger, msg.str());
+#endif
+
+ bool rc = false;
+ switch (d_context) {
+ case buffer_context::HOST_TO_DEVICE:
+ case buffer_context::HOST_TO_HOST:
+ // Adjust host buffer
+ rc = output_blocked_callback_logic(output_multiple, force, d_base, std::memmove);
+ break;
+
+ case buffer_context::DEVICE_TO_HOST:
+ case buffer_context::DEVICE_TO_DEVICE:
+ // Adjust "device" buffer
+ rc = output_blocked_callback_logic(
+ output_multiple, force, d_device_base, host_buffer::device_memmove);
+ break;
+
+ default:
+ std::ostringstream msg;
+ msg << "Unexpected context for host_buffer: " << d_context;
+ GR_LOG_ERROR(d_logger, msg.str());
+ throw std::runtime_error(msg.str());
+ }
+
+ return rc;
+}
+
+buffer_sptr host_buffer::make_host_buffer(int nitems,
+ size_t sizeof_item,
+ uint64_t downstream_lcm_nitems,
+ uint32_t downstream_max_out_mult,
+ block_sptr link,
+ block_sptr buf_owner)
+{
+ return buffer_sptr(new host_buffer(nitems,
+ sizeof_item,
+ downstream_lcm_nitems,
+ downstream_max_out_mult,
+ link,
+ buf_owner));
+}
+
+} /* namespace gr */