aboutsummaryrefslogtreecommitdiff
path: root/utils/ethosu_logd/dev_mem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ethosu_logd/dev_mem.cpp')
-rw-r--r--utils/ethosu_logd/dev_mem.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/utils/ethosu_logd/dev_mem.cpp b/utils/ethosu_logd/dev_mem.cpp
new file mode 100644
index 0000000..053cdd3
--- /dev/null
+++ b/utils/ethosu_logd/dev_mem.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dev_mem.hpp"
+
+#include <cstddef>
+#include <iostream>
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+namespace EthosU {
+namespace DevMem {
+
+/****************************************************************************
+ * Exception
+ ****************************************************************************/
+
+Exception::Exception(const char *msg) : msg(msg) {}
+
+Exception::Exception(const std::string &msg) : msg(msg) {}
+
+Exception::~Exception() throw() {}
+
+const char *Exception::what() const throw() {
+ return msg.c_str();
+}
+
+/****************************************************************************
+ * DevMem
+ ****************************************************************************/
+
+DevMem::DevMem(uintptr_t address, size_t size) :
+ base(nullptr), pageMask(sysconf(_SC_PAGESIZE) - 1), pageOffset(address & pageMask), size(size) {
+ int fd = ::open("/dev/mem", O_RDWR | O_SYNC);
+ if (fd < 0) {
+ throw Exception("Failed to open device");
+ }
+
+ base = reinterpret_cast<char *>(
+ ::mmap(nullptr, pageOffset + size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address & ~pageMask));
+ if (base == MAP_FAILED) {
+ throw Exception("MMap failed");
+ }
+
+ ::close(fd);
+}
+
+DevMem::~DevMem() {
+ ::munmap(base, pageOffset + size);
+}
+
+void DevMem::read(char *dst, size_t length, size_t offset) {
+ if (offset + length > size) {
+ throw Exception("Read failed");
+ }
+
+ // TODO Why do not std::copy() or memcpy work?
+ for (size_t i = 0; i < length; i++) {
+ dst[i] = base[pageOffset + offset + i];
+ }
+}
+
+void DevMem::write(char *src, size_t length, size_t offset) {
+ if (offset + length > size) {
+ throw Exception("Write failed");
+ }
+
+ // TODO Why do not std::copy() or memcpy work?
+ for (size_t i = 0; i < length; i++) {
+ base[pageOffset + offset + i] = src[i];
+ }
+}
+
+/****************************************************************************
+ * Log
+ ****************************************************************************/
+
+Log::Log(uintptr_t address, size_t size) : DevMem(address, size) {}
+
+void Log::clear() {
+ LogHeader header;
+ read(header, 0);
+
+ uint32_t rpos = header.write;
+ write(rpos, offsetof(LogHeader, read));
+}
+
+void Log::print() {
+ LogHeader header;
+ read(header, 0);
+
+ if (header.size < LOG_SIZE_MIN || header.size > LOG_SIZE_MAX) {
+ std::string msg = "Incorrect ring buffer values. size=" + std::to_string(header.size) +
+ ", read=" + std::to_string(header.read) + ", write=" + std::to_string(header.write);
+ throw Exception(msg.c_str());
+ }
+
+ size_t rpos = header.read;
+
+ // Skip forward if read is more than 'size' behind
+ if (rpos + header.size < header.write) {
+ rpos = header.write - header.size;
+ }
+
+ while (rpos < header.write) {
+ char c;
+ size_t offset = rpos++ % header.size + sizeof(header);
+ read(c, offset);
+ std::cout << c;
+ }
+}
+
+} // namespace DevMem
+} // namespace EthosU