From a7b22b7971e2efce430cebc295a802dd355b51e1 Mon Sep 17 00:00:00 2001 From: prime number Date: Wed, 25 Sep 2019 03:30:33 +0900 Subject: [PATCH] Well managed file descriptor and mmap-ed memory (#454) * implement FileDescriptor class, rewrite MappedMem class to RAII style --- dlk/python/dlk/templates/include/de10_nano.h | 17 +-- dlk/python/dlk/templates/include/memdriver.h | 149 +++++-------------- dlk/python/dlk/templates/src/network.tpl.cpp | 26 +--- 3 files changed, 41 insertions(+), 151 deletions(-) diff --git a/dlk/python/dlk/templates/include/de10_nano.h b/dlk/python/dlk/templates/include/de10_nano.h index fadda79ce..7de4b37bd 100644 --- a/dlk/python/dlk/templates/include/de10_nano.h +++ b/dlk/python/dlk/templates/include/de10_nano.h @@ -24,17 +24,6 @@ namespace de10_nano { // // TCA // -uint8_t* mapPhysicalMemory(size_t base, size_t size) { - int fd = open("/dev/mem", O_RDWR | O_SYNC, 0); - if (fd == -1) - throw std::system_error(errno, std::generic_category()); - int rw = PROT_READ | PROT_WRITE; - auto* mapped_base = reinterpret_cast(mmap(nullptr, size, rw, MAP_SHARED, fd, base)); - if (mapped_base == MAP_FAILED) - throw std::system_error(errno, std::generic_category()); - return mapped_base; -} - struct Csr { static constexpr uint32_t start = 0; static constexpr uint32_t admaInputAddress = 1; @@ -275,10 +264,8 @@ void RunTCA(unsigned long input_addr, unsigned long output_addr, unsigned long k unsigned use_threshold = (thresholds_addr != 0) ? 1 : 0; - static volatile uint32_t* csr = nullptr; - if (csr == nullptr) { - csr = reinterpret_cast(mapPhysicalMemory(HPS_TO_FPGA_LW_BASE, 0xFF)); - } + static MappedMem csr_mmap(HPS_TO_FPGA_LW_BASE, 0xFF); + static volatile uint32_t* csr = reinterpret_cast(csr_mmap.get()); auto tileWidth = 32u; auto tileHeight = 32u; auto p = calcParameters(in_h, in_w, in_c, tileWidth, tileHeight, out_c, k_h, k_w, input_addr, kernel_addr, thresholds_addr, output_addr, use_threshold == 1); diff --git a/dlk/python/dlk/templates/include/memdriver.h b/dlk/python/dlk/templates/include/memdriver.h index 22fa75498..805f392b7 100644 --- a/dlk/python/dlk/templates/include/memdriver.h +++ b/dlk/python/dlk/templates/include/memdriver.h @@ -21,127 +21,46 @@ limitations under the License. #include #include #include - -class MappedMem -{ -public: - using memtype = volatile void; - - MappedMem(unsigned long g_paddr, - uint32_t g_count, - uint32_t g_size) - : mem(nullptr), aligned_size(0) - { - memtype* aligned_vaddr; - unsigned long aligned_paddr; - - /* Align address to access size */ - g_paddr &= ~(g_size - 1); - - aligned_paddr = g_paddr & ~(4096 - 1); - aligned_size = g_paddr - aligned_paddr + (g_count * g_size); - aligned_size = (aligned_size + 4096 - 1) & ~(4096 - 1); - - int fd = -1; - if ((fd = open("/dev/mem", O_RDWR, 0)) < 0) - return; - - aligned_vaddr = mmap(nullptr, - aligned_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - fd, aligned_paddr); - - if (aligned_vaddr == MAP_FAILED) { - printf("Error mapping address %lx\n", aligned_paddr); - return; +#include +#include + +class FileDescriptor { + public: + FileDescriptor() : fd(-1) {} + FileDescriptor(int fd) : fd(fd) {} + ~FileDescriptor() { + if (fd >= 0) { + close(fd); } - - mem = (memtype *)((uint32_t)aligned_vaddr + (uint32_t)(g_paddr - aligned_paddr)); - close(fd); - } - - ~MappedMem() - { - if(mem != nullptr) - munmap((void*)mem, aligned_size); - } - - - template - memtype Write(T data) - { - T *mem_ptr = (T *) mem; - *mem_ptr = data; - } - - template - bool Check(T data) - { - T *mem_ptr = (T *) mem; - return *mem_ptr == data; - } - - - template - memtype Read(T &data) - { - T *mem_ptr = (T *) mem; - data = *mem_ptr; } + operator int() const { return fd; } + private: + int fd; +}; - - template - memtype Write(const T *data, unsigned int size) - { - T *mem_ptr = (T *) mem; - for(unsigned int i = 0; i < size; i++) - *mem_ptr++ = data[i]; - } - - - template - bool Check(const T *data, unsigned int size) - { - bool success = true; - T *mem_ptr = (T *) mem; - - for(unsigned int i = 0; i < size; i++) - { - success &= (*mem_ptr++ == data[i]); - if(!success) - break; +class MappedMem { + public: + MappedMem(std::size_t base, std::size_t size) : length(0) { + FileDescriptor fd(open("/dev/mem", O_RDWR | O_SYNC)); + if (fd == -1) { + return; } - - return success; - } - - - template - memtype Read(T *data, unsigned int size) - { - // volatile T* _data = data; - T *mem_ptr = (T *) mem; - for(unsigned int i = 0; i < size; i++) - data[i] = *mem_ptr++; + int rw = PROT_READ | PROT_WRITE; + ptr = mmap(nullptr, size, rw, MAP_SHARED, fd, base); + if (ptr == MAP_FAILED) { + throw std::system_error(errno, std::generic_category()); + } + length = size; } - - - memtype* get() - { - return mem; + ~MappedMem() { + if (ptr != MAP_FAILED) { + munmap(ptr, length); + } } - - -private: - MappedMem(); - MappedMem(const MappedMem &); - MappedMem& operator=(const MappedMem &); - -private: - memtype *mem; - uint32_t aligned_size; + void* get() const { return ptr; } + private: + void* ptr; + std::size_t length; }; - #endif diff --git a/dlk/python/dlk/templates/src/network.tpl.cpp b/dlk/python/dlk/templates/src/network.tpl.cpp index 8ce0949d9..25237ce54 100644 --- a/dlk/python/dlk/templates/src/network.tpl.cpp +++ b/dlk/python/dlk/templates/src/network.tpl.cpp @@ -63,27 +63,9 @@ limitations under the License. #include "operators.h" #ifdef RUN_ON_FPGA -#include -#include -#include -#include +#include "memdriver.h" #endif -namespace { - -uint8_t* mapPhysicalMemory(size_t base, size_t size) { - int fd = open("/dev/mem", O_RDWR | O_SYNC, 0); - if (fd == -1) - throw std::system_error(errno, std::generic_category()); - int rw = PROT_READ | PROT_WRITE; - auto* mapped_base = reinterpret_cast(mmap(nullptr, size, rw, MAP_SHARED, fd, base)); - if (mapped_base == MAP_FAILED) - throw std::system_error(errno, std::generic_category()); - return mapped_base; -} - -} // namespace - {% if config.debug -%} #include "c2numpy.h" @@ -259,13 +241,15 @@ bool Network::init() {{ '\n' -}} #if defined RUN_ON_FPGA - auto* kernel_buffer = mapPhysicalMemory(KERNEL_ADDR, total_kernel_size); + MappedMem kernel_mmap(KERNEL_ADDR, total_kernel_size); + auto kernel_buffer = reinterpret_cast(kernel_mmap.get()); {% for qconv in graph.convs(quantized_only=True) -%} {% set kernel = qconv.input_nodes[1] -%} std::memcpy(kernel_buffer + {{qconv.name}}_kernel_offset, {{kernel.name}}.data(), {{qconv.name}}_kernel_size); {% endfor -%} - auto* thresholds_buffer = mapPhysicalMemory(THRESHOLD_ADDR, total_thresholds_size); + MappedMem thresholds_mmap(THRESHOLD_ADDR, total_thresholds_size); + auto thresholds_buffer = reinterpret_cast(thresholds_mmap.get()); {% for qconv in graph.convs(quantized_only=True) -%} {% if qconv.has_thresholds -%} {% set thresholds = qconv.thresholds -%}