rogue
Loading...
Searching...
No Matches
MemMap.cpp
Go to the documentation of this file.
1
17#include "rogue/Directives.h"
18
20
21#include <fcntl.h>
22#include <inttypes.h>
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
28#include <cstdio>
29#include <cstring>
30#include <memory>
31#include <thread>
32
33#include "rogue/GeneralError.h"
34#include "rogue/GilRelease.h"
38
39namespace rh = rogue::hardware;
41
42#ifndef NO_PYTHON
43 #include <boost/python.hpp>
44namespace bp = boost::python;
45#endif
46
48rh::MemMapPtr rh::MemMap::create(uint64_t base, uint32_t size) {
49 rh::MemMapPtr r = std::make_shared<rh::MemMap>(base, size);
50 return (r);
51}
52
54rh::MemMap::MemMap(uint64_t base, uint32_t size) : rim::Slave(4, 0xFFFFFFFF) {
55 log_ = rogue::Logging::create("MemMap");
56
57 size_ = size;
58
59 fd_ = ::open(MAP_DEVICE, O_RDWR);
60
61 if (fd_ < 0) throw(rogue::GeneralError::create("MemMap::MemMap", "Failed to open device file: %s", MAP_DEVICE));
62
63 if ((map_ = reinterpret_cast<uint8_t*>(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, base))) ==
64 reinterpret_cast<void*>(-1)) {
65 ::close(fd_);
66 fd_ = -1;
67 throw(rogue::GeneralError::create("MemMap::MemMap", "Failed to map memory to user space."));
68 }
69
70 log_->debug("Created map to 0x%" PRIx64 " with size 0x%" PRIx32, base, size);
71
72 threadEn_ = true;
73 try {
74 thread_ = std::make_unique<std::thread>(&rh::MemMap::runThread, this);
75 } catch (...) {
76 threadEn_ = false;
77 munmap(reinterpret_cast<void*>(const_cast<uint8_t*>(map_)), size_);
78 map_ = nullptr;
79 ::close(fd_);
80 fd_ = -1;
81 throw;
82 }
83}
84
86rh::MemMap::~MemMap() {
87 this->stop();
88}
89
90void rh::MemMap::stop() {
91 if (threadEn_) {
93 threadEn_ = false;
94 queue_.stop();
95 thread_->join();
96 thread_.reset();
97 munmap(reinterpret_cast<void*>(const_cast<uint8_t*>(map_)), size_);
98 ::close(fd_);
99 fd_ = -1;
100 }
101}
102
104void rh::MemMap::doTransaction(rim::TransactionPtr tran) {
105 rogue::GilRelease noGil;
106 queue_.push(tran);
107}
108
110void rh::MemMap::runThread() {
112
113 uint32_t* tPtr;
114 uint32_t* mPtr;
115 uint32_t count;
116
117 log_->logThreadId();
118
119 while (threadEn_) {
120 if ((tran = queue_.pop()) != NULL) {
121 count = 0;
122
123 rim::TransactionLockPtr lock = tran->lock();
124
125 if (tran->expired()) {
126 log_->warning("Transaction expired. Id=%" PRIu32, tran->id());
127 tran.reset();
128 continue;
129 }
130
131 if ((tran->size() % 4) != 0) {
132 tran->error("Invalid transaction size %" PRIu32 ", must be an integer number of 4 bytes", tran->size());
133 tran.reset();
134 continue;
135 }
136
137 // Check that the address is legal
138 if ((tran->address() + tran->size()) > size_) {
139 tran->error("Request transaction to address 0x%" PRIx64 " with size %" PRIu32 " is out of bounds",
140 tran->address(),
141 tran->size());
142 tran.reset();
143 continue;
144 }
145
146 tPtr = reinterpret_cast<uint32_t*>(tran->begin());
147 mPtr = const_cast<uint32_t*>(reinterpret_cast<volatile uint32_t*>(map_ + tran->address()));
148
149 while (count != tran->size()) {
150 // Write or post
151 if (tran->type() == rim::Write || tran->type() == rim::Post) *mPtr = *tPtr;
152
153 // Read or verify
154 else
155 *tPtr = *mPtr;
156
157 ++mPtr;
158 ++tPtr;
159 count += 4;
160 }
161
162 log_->debug("Transaction id=%" PRIu32 ", addr 0x%08" PRIx64 ". Size=%" PRIu32 ", type=%" PRIu32,
163 tran->id(),
164 tran->address(),
165 tran->size(),
166 tran->type());
167 tran->done();
168 }
169 }
170}
171
172void rh::MemMap::setup_python() {
173#ifndef NO_PYTHON
174
175 bp::class_<rh::MemMap, rh::MemMapPtr, bp::bases<rim::Slave>, boost::noncopyable>("MemMap",
176 bp::init<uint64_t, uint32_t>());
177
178 bp::implicitly_convertible<rh::MemMapPtr, rim::SlavePtr>();
179#endif
180}
#define MAP_DEVICE
Definition MemMap.h:33
static GeneralError create(std::string src, const char *fmt,...)
Creates a formatted error instance.
RAII helper that releases the Python GIL for a scope.
Definition GilRelease.h:36
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
Definition Logging.cpp:95
std::shared_ptr< rogue::hardware::MemMap > MemMapPtr
Shared pointer alias for MemMap.
Definition MemMap.h:133
std::shared_ptr< rogue::interfaces::memory::TransactionLock > TransactionLockPtr
Shared pointer alias for TransactionLock.
static const uint32_t Write
Memory write transaction type.
Definition Constants.h:43
std::shared_ptr< rogue::interfaces::memory::Transaction > TransactionPtr
Shared pointer alias for Transaction.
static const uint32_t Post
Memory posted write transaction type.
Definition Constants.h:50