aboutsummaryrefslogtreecommitdiff
path: root/utils/ethosu_logd/dev_mem.cpp
blob: 053cdd35da4b85ac2fa9ef4d2e0422459d994e82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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