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 throw(rogue::GeneralError("AxiMemMap::AxiMemMap",
65 R"(Bad kernel driver version detected. Please re-compile kernel driver.
66 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.
67 To use later versions (64-bit address API),, you will need to upgrade both rogue and aes-stream-driver at the same time to:
68 \t\taes-stream-driver = v5.16.0 (or later)
69 \t\trogue = v5.13.0 (or later))"));
70 }
71
72 // Check for mismatch in the rogue/loaded_driver API versions
73 if (dmaCheckVersion(fd_) < 0) {
74 ::close(fd_);
76 "AxiMemMap::AxiMemMap",
77 "Rogue DmaDriver.h API Version (DMA_VERSION) does not match the aes-stream-driver API version"));
78 }
79
80 // Start read thread
81 threadEn_ = true;
82 thread_ = new std::thread(&rha::AxiMemMap::runThread, this);
83}
84
86rha::AxiMemMap::~AxiMemMap() {
87 this->stop();
88}
89
90// Stop
91void rha::AxiMemMap::stop() {
92 if (threadEn_) {
94 threadEn_ = false;
95 queue_.stop();
96 thread_->join();
97 ::close(fd_);
98 }
99}
100
102void rha::AxiMemMap::doTransaction(rim::TransactionPtr tran) {
103 rogue::GilRelease noGil;
104 queue_.push(tran);
105}
106
108void rha::AxiMemMap::runThread() {
110 rim::Transaction::iterator it;
111
112 uint32_t count;
113 uint32_t data;
114 uint32_t dataSize;
115 int32_t ret;
116 uint8_t* ptr;
117
118 dataSize = sizeof(uint32_t);
119 ptr = reinterpret_cast<uint8_t*>(&data);
120
121 log_->logThreadId();
122
123 while (threadEn_) {
124 if ((tran = queue_.pop()) != NULL) {
125 if ((tran->size() % dataSize) != 0) {
126 tran->error("Invalid transaction size %" PRIu32 ", must be an integer number of %" PRIu32 " bytes",
127 tran->size(),
128 dataSize);
129 tran.reset();
130 continue;
131 }
132
133 count = 0;
134 ret = 0;
135
136 rim::TransactionLockPtr lock = tran->lock();
137
138 if (tran->expired()) {
139 log_->warning("Transaction expired. Id=%" PRIu32, tran->id());
140 tran.reset();
141 continue;
142 }
143
144 it = tran->begin();
145
146 while ((ret == 0) && (count != tran->size())) {
147 if (tran->type() == rim::Write || tran->type() == rim::Post) {
148 // Assume transaction has a contiguous memory block
149 std::memcpy(ptr, it, dataSize);
150 ret = dmaWriteRegister(fd_, tran->address() + count, data);
151 } else {
152 ret = dmaReadRegister(fd_, tran->address() + count, &data);
153 std::memcpy(it, ptr, dataSize);
154 }
155 count += dataSize;
156 it += dataSize;
157 }
158
159 log_->debug("Transaction id=%" PRIu32 ", addr 0x%016" PRIx64 ". Size=%" PRIu32 ", type=%" PRIu32
160 ", data=0x%08" PRIu32,
161 tran->id(),
162 tran->address(),
163 tran->size(),
164 tran->type(),
165 data);
166 if (ret != 0)
167 tran->error("Memory transaction failed with error code %" PRIi32 ", see driver error codes", ret);
168 else
169 tran->done();
171 }
172}
173
174void rha::AxiMemMap::setup_python() {
175#ifndef NO_PYTHON
176
177 bp::class_<rha::AxiMemMap, rha::AxiMemMapPtr, bp::bases<rim::Slave>, boost::noncopyable>("AxiMemMap",
178 bp::init<std::string>());
179
180 bp::implicitly_convertible<rha::AxiMemMapPtr, rim::SlavePtr>();
181#endif
182}
static ssize_t dmaGetApiVersion(int32_t fd)
Get API version of the DMA driver.
Definition DmaDriver.h:881
static ssize_t dmaReadRegister(int32_t fd, uint64_t address, uint32_t *data)
Read a value from a DMA register.
Definition DmaDriver.h:916
static ssize_t dmaWriteRegister(int32_t fd, uint64_t address, uint32_t data)
Write to a DMA register.
Definition DmaDriver.h:896
static ssize_t dmaCheckVersion(int32_t fd)
Check API version of the DMA driver.
Definition DmaDriver.h:866
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:60
std::shared_ptr< rogue::hardware::axi::AxiMemMap > AxiMemMapPtr
Shared pointer alias for AxiMemMap.
Definition AxiMemMap.h:125
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