41 #include <boost/python.hpp>
42namespace bp = boost::python;
45std::map<std::string, std::shared_ptr<rha::AxiStreamDmaShared> > rha::AxiStreamDma::sharedBuffers_;
47rha::AxiStreamDmaShared::AxiStreamDmaShared(std::string path) {
59 std::map<std::string, rha::AxiStreamDmaSharedPtr>::iterator it;
63 if ((it = sharedBuffers_.find(path)) != sharedBuffers_.end()) {
65 log->debug(
"Reusing existing shared file descriptor for %s", path.c_str());
69 ret = std::make_shared<rha::AxiStreamDmaShared>(path);
70 log->debug(
"Opening new shared file descriptor for %s", path.c_str());
76 log->debug(
"Shared file descriptor already opened for %s", path.c_str());
82 log->debug(
"Zero copy is disabled. Not Mapping Buffers for %s", path.c_str());
87 if ((ret->fd = ::open(path.c_str(), O_RDWR)) < 0)
94 R
"(Bad kernel driver version detected. Please re-compile kernel driver.
95 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.
96 To use later versions (64-bit address API),, you will need to upgrade both rogue and aes-stream-driver at the same time to:
97 \t\taes-stream-driver = v5.16.0 (or later)
98 \t\trogue = v5.13.0 (or later))"));
105 "AxiStreamDma::openShared",
106 "Rogue DmaDriver.h API Version (DMA_VERSION) does not match the aes-stream-driver API version"));
111 ret->rawBuff =
dmaMapDma(ret->fd, &(ret->bCount), &(ret->bSize));
112 if (ret->rawBuff == NULL) {
116 uint32_t mapSize = ret->bCount + 8192;
120 "AxiStreamDma::openShared",
121 "Failed to map dma buffers. Increase vm map limit to : sudo sysctl -w vm.max_map_count=%i",
124 log->debug(
"Mapped buffers. bCount = %i, bSize=%i for %s", ret->bCount, ret->bSize, path.c_str());
127 sharedBuffers_.insert(std::pair<std::string, rha::AxiStreamDmaSharedPtr>(path, ret));
135 if (desc->openCount == 0) {
136 if (desc->rawBuff != NULL) {
144 desc->rawBuff = NULL;
149rha::AxiStreamDmaPtr rha::AxiStreamDma::create(std::string path, uint32_t dest,
bool ssiEnable) {
154void rha::AxiStreamDma::zeroCopyDisable(std::string path) {
155 std::map<std::string, rha::AxiStreamDmaSharedPtr>::iterator it;
158 if ((it = sharedBuffers_.find(path)) != sharedBuffers_.end())
160 "zeroCopyDisable can't be called twice or after a device has been opened"));
164 ret->zCopyEn =
false;
166 sharedBuffers_.insert(std::pair<std::string, rha::AxiStreamDmaSharedPtr>(path, ret));
170rha::AxiStreamDma::AxiStreamDma(std::string path, uint32_t dest,
bool ssiEnable) {
178 std::shared_ptr<int> scopePtr = std::make_shared<int>(0);
187 desc_ = openShared(path, log_);
189 if (desc_->bCount >= 1000) retThold_ = 80;
192 if ((fd_ = ::open(path.c_str(), O_RDWR)) < 0) {
199 if (desc_->rawBuff == NULL) {
203 if (desc_->bCount >= 1000) retThold_ = 80;
212 "Failed to open device file %s with dest 0x%" PRIx32
213 "! Another process may already have it open!",
220 thread_ =
new std::thread(&rha::AxiStreamDma::runThread,
this, std::weak_ptr<int>(scopePtr));
224 pthread_setname_np(thread_->native_handle(),
"AxiStreamDma");
229rha::AxiStreamDma::~AxiStreamDma() {
233void rha::AxiStreamDma::stop() {
248void rha::AxiStreamDma::setTimeout(uint32_t timeout) {
250 div_t divResult = div(timeout, 1000000);
251 timeout_.tv_sec = divResult.quot;
252 timeout_.tv_usec = divResult.rem;
257void rha::AxiStreamDma::setDriverDebug(uint32_t level) {
262void rha::AxiStreamDma::dmaAck() {
267ris::FramePtr rha::AxiStreamDma::acceptReq(uint32_t size,
bool zeroCopyEn) {
277 if (size > desc_->bSize)
278 buffSize = desc_->bSize;
283 if (zeroCopyEn ==
false || desc_->rawBuff == NULL) {
284 frame = reqLocalFrame(size,
false);
291 frame = ris::Frame::create();
295 while (alloc < size) {
306 if (select(fd_ + 1, NULL, &fds, NULL, &tout) <= 0) {
307 log_->critical(
"AxiStreamDma::acceptReq: Timeout waiting for outbound buffer after %" PRIuLEAST32
308 ".%" PRIuLEAST32
" seconds! May be caused by outbound back pressure.",
320 buff = createBuffer(desc_->rawBuff[res], 0x80000000 | res, buffSize, desc_->bSize);
321 frame->appendBuffer(buff);
344 if (frame->getError()) {
345 log_->warning(
"Dumping errored frame");
350 ris::Frame::BufferIterator it;
351 for (it = frame->beginBuffer(); it != frame->endBuffer(); ++it) {
355 if (it == frame->beginBuffer()) {
356 fuser = frame->getFirstUser();
357 if (enSsi_) fuser |= 0x2;
363 if (it == (frame->endBuffer() - 1)) {
365 luser = frame->getLastUser();
374 meta = (*it)->getMeta();
377 if ((meta & 0x80000000) != 0) {
381 if ((meta & 0x40000000) == 0) {
393 (*it)->setMeta(meta);
408 if (select(fd_ + 1, NULL, &fds, NULL, &tout) <= 0) {
409 log_->critical(
"AxiStreamDma::acceptFrame: Timeout waiting for outbound write after %" PRIuLEAST32
410 ".%" PRIuLEAST32
" seconds! May be caused by outbound back pressure.",
426 if (emptyFrame) frame->clear();
430void rha::AxiStreamDma::retBuffer(uint8_t* data, uint32_t meta, uint32_t size) {
437 if ((meta & 0x80000000) != 0) {
440 if ((fd_ >= 0) && ((meta & 0x40000000) == 0)) {
443 printf(
"Adding to queue\n");
444 retQueue_.push(meta);
447 if ( (count = retQueue_.size()) >= retThold_ ) {
448 printf(
"Return count=%" PRIu32
"\n", count);
449 if ( count > 100 ) count = 100;
450 for (x=0; x < count; x++) ret[x] = retQueue_.pop() & 0x3FFFFFFF;
453 throw(
rogue::GeneralError(
"AxiStreamDma::retBuffer",
"AXIS Return Buffer Call Failed!!!!"));
455 decCounter(size*count);
456 printf(
"Return done\n");
461 throw(
rogue::GeneralError(
"AxiStreamDma::retBuffer",
"AXIS Return Buffer Call Failed!!!!"));
469 Pool::retBuffer(data, meta, size);
474void rha::AxiStreamDma::runThread(std::weak_ptr<int> lockPtr) {
476 uint32_t meta[RxBufferCount];
477 uint32_t rxFlags[RxBufferCount];
478 uint32_t rxError[RxBufferCount];
479 int32_t rxSize[RxBufferCount];
495 while (!lockPtr.expired())
continue;
500 frame = ris::Frame::create();
512 if (select(fd_ + 1, &fds, NULL, NULL, &tout) > 0) {
514 if (desc_->rawBuff == NULL) {
516 buff[0] = allocBuffer(desc_->bSize, NULL);
519 rxSize[0] =
dmaRead(fd_, buff[0]->begin(), buff[0]->getAvailable(), rxFlags, rxError, NULL);
528 rxCount =
dmaReadBulkIndex(fd_, RxBufferCount, rxSize, meta, rxFlags, rxError, NULL);
531 for (x = 0; x < rxCount; x++)
532 buff[x] = createBuffer(desc_->rawBuff[meta[x]], 0x80000000 | meta[x], desc_->bSize, desc_->bSize);
536 if (rxCount < 0)
throw(
rogue::GeneralError(
"AxiStreamDma::runThread",
"DMA Interface Failure!"));
539 for (x = 0; x < rxCount; x++) {
544 buff[x]->setPayload(rxSize[x]);
546 error = frame->getError();
549 error |= (rxError[x] & 0xFF);
552 if (frame->isEmpty()) frame->setFirstUser(fuser & 0xFF);
556 frame->setLastUser(luser & 0xFF);
557 if (enSsi_ && ((luser & 0x1) != 0)) error |= 0x80;
560 frame->setError(error);
561 frame->appendBuffer(buff[x]);
567 frame = ris::Frame::create();
575std::string rha::AxiStreamDma::getGitVersion() {
580uint32_t rha::AxiStreamDma::getApiVersion() {
585uint32_t rha::AxiStreamDma::getBuffSize() {
590uint32_t rha::AxiStreamDma::getRxBuffCount() {
595uint32_t rha::AxiStreamDma::getRxBuffinUserCount() {
600uint32_t rha::AxiStreamDma::getRxBuffinHwCount() {
605uint32_t rha::AxiStreamDma::getRxBuffinPreHwQCount() {
610uint32_t rha::AxiStreamDma::getRxBuffinSwQCount() {
615uint32_t rha::AxiStreamDma::getRxBuffMissCount() {
620uint32_t rha::AxiStreamDma::getTxBuffCount() {
625uint32_t rha::AxiStreamDma::getTxBuffinUserCount() {
630uint32_t rha::AxiStreamDma::getTxBuffinHwCount() {
635uint32_t rha::AxiStreamDma::getTxBuffinPreHwQCount() {
640uint32_t rha::AxiStreamDma::getTxBuffinSwQCount() {
645uint32_t rha::AxiStreamDma::getTxBuffMissCount() {
649void rha::AxiStreamDma::setup_python() {
652 bp::class_<rha::AxiStreamDma, rha::AxiStreamDmaPtr, bp::bases<ris::Master, ris::Slave>, boost::noncopyable>(
654 bp::init<std::string, uint32_t, bool>())
655 .def(
"setDriverDebug", &rha::AxiStreamDma::setDriverDebug)
656 .def(
"dmaAck", &rha::AxiStreamDma::dmaAck)
657 .def(
"setTimeout", &rha::AxiStreamDma::setTimeout)
658 .def(
"getGitVersion", &rha::AxiStreamDma::getGitVersion)
659 .def(
"getApiVersion", &rha::AxiStreamDma::getApiVersion)
660 .def(
"getBuffSize", &rha::AxiStreamDma::getBuffSize)
661 .def(
"getRxBuffCount", &rha::AxiStreamDma::getRxBuffCount)
662 .def(
"getRxBuffinUserCount", &rha::AxiStreamDma::getRxBuffinUserCount)
663 .def(
"getRxBuffinHwCount", &rha::AxiStreamDma::getRxBuffinHwCount)
664 .def(
"getRxBuffinPreHwQCount", &rha::AxiStreamDma::getRxBuffinPreHwQCount)
665 .def(
"getRxBuffinSwQCount", &rha::AxiStreamDma::getRxBuffinSwQCount)
666 .def(
"getRxBuffMissCount", &rha::AxiStreamDma::getRxBuffMissCount)
667 .def(
"getTxBuffCount", &rha::AxiStreamDma::getTxBuffCount)
668 .def(
"getTxBuffinUserCount", &rha::AxiStreamDma::getTxBuffinUserCount)
669 .def(
"getTxBuffinHwCount", &rha::AxiStreamDma::getTxBuffinHwCount)
670 .def(
"getTxBuffinPreHwQCount", &rha::AxiStreamDma::getTxBuffinPreHwQCount)
671 .def(
"getTxBuffinSwQCount", &rha::AxiStreamDma::getTxBuffinSwQCount)
672 .def(
"getTxBuffMissCount", &rha::AxiStreamDma::getTxBuffMissCount)
673 .def(
"zeroCopyDisable", &rha::AxiStreamDma::zeroCopyDisable);
675 bp::implicitly_convertible<rha::AxiStreamDmaPtr, ris::MasterPtr>();
676 bp::implicitly_convertible<rha::AxiStreamDmaPtr, ris::SlavePtr>();
static uint32_t axisGetLuser(uint32_t flags)
Extracts last-user flag from packed AXIS flags.
static uint32_t axisSetFlags(uint32_t fuser, uint32_t luser, uint32_t cont)
Packs AXIS first-user, last-user, and continuation bits.
static uint32_t axisGetFuser(uint32_t flags)
Extracts first-user flag from packed AXIS flags.
static void axisReadAck(int32_t fd)
Issues AXIS read-acknowledge ioctl command.
static uint32_t axisGetCont(uint32_t flags)
Extracts continuation flag from packed AXIS flags.
static std::string dmaGetGitVersion(int32_t fd)
Get the DMA Driver's Git Version.
static ssize_t dmaGetTxBuffinPreHwQCount(int32_t fd)
Get the transmit buffer count in pre-hardware queue.
static ssize_t dmaGetTxBuffCount(int32_t fd)
Get the transmit buffer count.
static ssize_t dmaGetTxBuffMissCount(int32_t fd)
Get the transmit buffer missing count.
static ssize_t dmaGetRxBuffinHwCount(int32_t fd)
Get the receive buffer count in hardware.
static ssize_t dmaGetApiVersion(int32_t fd)
Get API version of the DMA driver.
static ssize_t dmaWriteIndex(int32_t fd, uint32_t index, size_t size, uint32_t flags, uint32_t dest)
Writes data to a DMA channel using an index.
static void dmaInitMaskBytes(uint8_t *mask)
Initialize DMA mask byte array.
static void dmaAddMaskBytes(uint8_t *mask, uint32_t dest)
Add a destination to the DMA mask byte array.
static ssize_t dmaReadBulkIndex(int32_t fd, uint32_t count, int32_t *ret, uint32_t *index, uint32_t *flags, uint32_t *error, uint32_t *dest)
Receive frame and access memory-mapped buffer.
static ssize_t dmaSetMaskBytes(int32_t fd, uint8_t *mask)
Set mask byte array to the driver.
static ssize_t dmaGetRxBuffinUserCount(int32_t fd)
Get the receive buffer count in user.
static ssize_t dmaGetTxBuffinHwCount(int32_t fd)
Get the transmit buffer count in hardware.
static ssize_t dmaGetBuffSize(int32_t fd)
Get the buffer size.
static ssize_t dmaGetRxBuffinSwQCount(int32_t fd)
Get the receive buffer count in software queue.
static ssize_t dmaGetRxBuffCount(int32_t fd)
Get the receive buffer count.
static int32_t dmaGetIndex(int32_t fd)
Get the current write buffer index.
static ssize_t dmaGetRxBuffinPreHwQCount(int32_t fd)
Get the receive buffer count in pre-hardware queue.
static ssize_t dmaRetIndex(int32_t fd, uint32_t index)
Post an index back to the DMA.
static ssize_t dmaSetDebug(int32_t fd, uint32_t level)
Set debugging level for DMA operations.
static ssize_t dmaGetTxBuffinSwQCount(int32_t fd)
Get the transmit buffer count in software queue.
static ssize_t dmaGetBuffCount(int32_t fd)
Get the buffer count.
static ssize_t dmaCheckVersion(int32_t fd)
Check API version of the DMA driver.
static void ** dmaMapDma(int32_t fd, uint32_t *count, uint32_t *size)
Map user space to DMA buffers.
static ssize_t dmaUnMapDma(int32_t fd, void **buffer)
Unmap user space from DMA buffers.
static ssize_t dmaRead(int32_t fd, void *buf, size_t maxSize, uint32_t *flags, uint32_t *error, uint32_t *dest)
Receive Frame.
static ssize_t dmaGetTxBuffinUserCount(int32_t fd)
Get the transmit buffer count in user.
static ssize_t dmaWrite(int32_t fd, const void *buf, size_t size, uint32_t flags, uint32_t dest)
Writes data to a DMA channel.
static ssize_t dmaGetRxBuffMissCount(int32_t fd)
Get the receive buffer missing count.
static ssize_t dmaRetIndexes(int32_t fd, uint32_t count, uint32_t *indexes)
Post multiple indices back to the DMA.
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.
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
std::shared_ptr< rogue::hardware::axi::AxiStreamDma > AxiStreamDmaPtr
std::shared_ptr< rogue::hardware::axi::AxiStreamDmaShared > AxiStreamDmaSharedPtr
std::shared_ptr< rogue::interfaces::stream::Buffer > BufferPtr
Shared pointer alias for Buffer.
std::shared_ptr< rogue::interfaces::stream::Frame > FramePtr
Shared pointer alias for Frame.
std::shared_ptr< rogue::interfaces::stream::FrameLock > FrameLockPtr
Shared pointer alias for FrameLock.
std::shared_ptr< rogue::Logging > LoggingPtr
Shared pointer alias for Logging.
void defaultTimeout(struct timeval &tout)
Returns Rogue default timeout as a timeval.