rogue
Loading...
Searching...
No Matches
AxiMemMap.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 <string>
32#include <thread>
33
34#include "rogue/GeneralError.h"
35#include "rogue/GilRelease.h"
40
41namespace rha = rogue::hardware::axi;
43
44#ifndef NO_PYTHON
45 #include <boost/python.hpp>
46namespace bp = boost::python;
47#endif
48
50rha::AxiMemMapPtr rha::AxiMemMap::create(std::string path) {
51 rha::AxiMemMapPtr r = std::make_shared<rha::AxiMemMap>(path);
52 return (r);
53}
54
56rha::AxiMemMap::AxiMemMap(std::string path) : rim::Slave(4, 0xFFFFFFFF) {
57 fd_ = ::open(path.c_str(), O_RDWR);
58 log_ = rogue::Logging::create("axi.AxiMemMap");
59 if (fd_ < 0)
60 throw(rogue::GeneralError::create("AxiMemMap::AxiMemMap", "Failed to open device file: %s", path.c_str()));
61
62 // Check driver version ( ApiVersion 0x05 (or less) is the 32-bit address version)
63 if (dmaGetApiVersion(fd_) < 0x06) {
64 ::close(fd_);
65 fd_ = -1;
66 throw(rogue::GeneralError("AxiMemMap::AxiMemMap",
67 R"(Bad kernel driver version detected. Please re-compile kernel driver.
68 Note that aes-stream-driver (v5.15.2 or earlier) and rogue (v5.11.1 or earlier) are compatible with the 32-bit address API.
69 To use later versions (64-bit address API),, you will need to upgrade both rogue and aes-stream-driver at the same time to:
70 \t\taes-stream-driver = v5.16.0 (or later)
71 \t\trogue = v5.13.0 (or later))"));
72 }
73
74 // Check for mismatch in the rogue/loaded_driver API versions
75 if (dmaCheckVersion(fd_) < 0) {
76 ::close(fd_);
77 fd_ = -1;
79 "AxiMemMap::AxiMemMap",
80 "Rogue DmaDriver.h API Version (DMA_VERSION) does not match the aes-stream-driver API version"));
81 }
82
83 threadEn_ = true;
84 try {
85 thread_ = std::make_unique<std::thread>(&rha::AxiMemMap::runThread, this);
86 } catch (...) {
87 threadEn_ = false;
88 ::close(fd_);
89 fd_ = -1;
90 throw;
91 }
92}
93
95rha::AxiMemMap::~AxiMemMap() {
96 this->stop();
97}
98
99// Stop
100void rha::AxiMemMap::stop() {
101 if (threadEn_) {
102 rogue::GilRelease noGil;
103 threadEn_ = false;
104 queue_.stop();
105 thread_->join();
106 thread_.reset();
107 ::close(fd_);
108 fd_ = -1;
110}
111
113void rha::AxiMemMap::doTransaction(rim::TransactionPtr tran) {
114 rogue::GilRelease noGil;
115 queue_.push(tran);
116}
117
119void rha::AxiMemMap::runThread() {
121 rim::Transaction::iterator it;
122
123 uint32_t count;
124 uint32_t data;
125 uint32_t dataSize;
126 int32_t ret;
127 uint8_t* ptr;
128
129 dataSize = sizeof(uint32_t);
130 ptr = reinterpret_cast<uint8_t*>(&data);
131
132 log_->logThreadId();
133
134 while (threadEn_) {
135 if ((tran = queue_.pop()) != NULL) {
136 if ((tran->size() % dataSize) != 0) {
137 tran->error("Invalid transaction size %" PRIu32 ", must be an integer number of %" PRIu32 " bytes",
138 tran->size(),
139 dataSize);
140 tran.reset();
141 continue;
142 }
143
144 count = 0;
145 ret = 0;
146
147 rim::TransactionLockPtr lock = tran->lock();
148
149 if (tran->expired()) {
150 log_->warning("Transaction expired. Id=%" PRIu32, tran->id());
151 tran.reset();
152 continue;
153 }
154
155 it = tran->begin();
156
157 while ((ret == 0) && (count != tran->size())) {
158 if (tran->type() == rim::Write || tran->type() == rim::Post) {
159 // Assume transaction has a contiguous memory block
160 std::memcpy(ptr, it, dataSize);
161 ret = dmaWriteRegister(fd_, tran->address() + count, data);
162 } else {
163 ret = dmaReadRegister(fd_, tran->address() + count, &data);
164 std::memcpy(it, ptr, dataSize);
165 }
166 count += dataSize;
167 it += dataSize;
168 }
169
170 log_->debug("Transaction id=%" PRIu32 ", addr 0x%016" PRIx64 ". Size=%" PRIu32 ", type=%" PRIu32
171 ", data=0x%08" PRIu32,
172 tran->id(),
173 tran->address(),
174 tran->size(),
175 tran->type(),
176 data);
177 if (ret != 0)
178 tran->error("Memory transaction failed with error code %" PRIi32 ", see driver error codes", ret);
179 else
180 tran->done();
182 }
183}
184
185void rha::AxiMemMap::setup_python() {
186#ifndef NO_PYTHON
187
188 bp::class_<rha::AxiMemMap, rha::AxiMemMapPtr, bp::bases<rim::Slave>, boost::noncopyable>("AxiMemMap",
189 bp::init<std::string>());
190
191 bp::implicitly_convertible<rha::AxiMemMapPtr, rim::SlavePtr>();
192#endif
193}
static ssize_t dmaGetApiVersion(int32_t fd)
Get API version of the DMA driver.
Definition DmaDriver.h:930
static ssize_t dmaReadRegister(int32_t fd, uint64_t address, uint32_t *data)
Read a value from a DMA register.
Definition DmaDriver.h:965
static ssize_t dmaWriteRegister(int32_t fd, uint64_t address, uint32_t data)
Write to a DMA register.
Definition DmaDriver.h:945
static ssize_t dmaCheckVersion(int32_t fd)
Check API version of the DMA driver.
Definition DmaDriver.h:915
Generic Rogue exception type.
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::axi::AxiMemMap > AxiMemMapPtr
Shared pointer alias for AxiMemMap.
Definition AxiMemMap.h:130
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