42 #include <boost/python.hpp>
43namespace bp = boost::python;
46std::map<std::string, std::shared_ptr<rha::AxiStreamDmaShared> > rha::AxiStreamDma::sharedBuffers_;
51rha::AxiStreamDmaShared::AxiStreamDmaShared(std::string path) {
70 std::map<std::string, rha::AxiStreamDmaSharedPtr>::iterator it;
74 if ((it = sharedBuffers_.find(path)) != sharedBuffers_.end()) {
76 log->debug(
"Reusing existing shared file descriptor for %s", path.c_str());
81 log->debug(
"Shared file descriptor already opened for %s", path.c_str());
92 log->debug(
"Zero copy is disabled. Not Mapping Buffers for %s", path.c_str());
101 ret = std::make_shared<rha::AxiStreamDmaShared>(path);
102 log->debug(
"Opening new shared file descriptor for %s", path.c_str());
106 if ((ret->fd = ::open(path.c_str(), O_RDWR)) < 0)
125 R
"(Bad kernel driver version detected. Please re-compile kernel driver.
126 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.
127 To use later versions (64-bit address API),, you will need to upgrade both rogue and aes-stream-driver at the same time to:
128 \t\taes-stream-driver = v5.16.0 (or later)
129 \t\trogue = v5.13.0 (or later))"));
137 "AxiStreamDma::openShared",
138 "Rogue DmaDriver.h API Version (DMA_VERSION) does not match the aes-stream-driver API version"));
143 ret->rawBuff =
dmaMapDma(ret->fd, &(ret->bCount), &(ret->bSize));
144 if (ret->rawBuff == NULL) {
157 "AxiStreamDma::openShared",
158 "Failed to map dma buffers. Increase vm map limit to : sudo sysctl -w vm.max_map_count=%i",
161 log->debug(
"Mapped buffers. bCount = %i, bSize=%i for %s", ret->bCount, ret->bSize, path.c_str());
165 sharedBuffers_.insert(std::pair<std::string, rha::AxiStreamDmaSharedPtr>(path, ret));
175 if (desc->openCount == 0) {
176 if (desc->rawBuff != NULL) {
184 if (desc->fd != -1) {
190 desc->rawBuff = NULL;
195rha::AxiStreamDmaPtr rha::AxiStreamDma::create(std::string path, uint32_t dest,
bool ssiEnable) {
200void rha::AxiStreamDma::zeroCopyDisable(std::string path) {
203 std::map<std::string, rha::AxiStreamDmaSharedPtr>::iterator it;
206 if ((it = sharedBuffers_.find(path)) != sharedBuffers_.end())
208 "zeroCopyDisable can't be called twice or after a device has been opened"));
212 ret->zCopyEn =
false;
214 sharedBuffers_.insert(std::pair<std::string, rha::AxiStreamDmaSharedPtr>(path, ret));
218rha::AxiStreamDma::AxiStreamDma(std::string path, uint32_t dest,
bool ssiEnable) {
226 std::shared_ptr<int> scopePtr = std::make_shared<int>(0);
235 desc_ = openShared(path, log_);
238 if ((fd_ = ::open(path.c_str(), O_RDWR)) < 0) {
248 if (fd_ >= FD_SETSIZE) {
254 "fd %d for %s exceeds FD_SETSIZE (%d); too many open files in process",
271 if (desc_->rawBuff == NULL) {
275 if (desc_->bCount >= 1000) retThold_ = 80;
286 "Failed to open device file %s with dest 0x%" PRIx32
287 "! Another process may already have it open!",
294 thread_ = std::make_unique<std::thread>(&rha::AxiStreamDma::runThread,
this, std::weak_ptr<int>(scopePtr));
305 pthread_setname_np(thread_->native_handle(),
"AxiStreamDma");
310rha::AxiStreamDma::~AxiStreamDma() {
314void rha::AxiStreamDma::stop() {
327 if (thread_ && thread_->joinable()) {
349void rha::AxiStreamDma::setTimeout(uint32_t timeout) {
351 div_t divResult = div(timeout, 1000000);
352 timeout_.tv_sec = divResult.quot;
353 timeout_.tv_usec = divResult.rem;
358void rha::AxiStreamDma::setDriverDebug(uint32_t level) {
363void rha::AxiStreamDma::dmaAck() {
368ris::FramePtr rha::AxiStreamDma::acceptReq(uint32_t size,
bool zeroCopyEn) {
381 if (!desc_ || fd_ < 0)
383 "instance has been stopped or did not finish construction");
386 if (size > desc_->bSize)
387 buffSize = desc_->bSize;
392 if (zeroCopyEn ==
false || desc_->rawBuff == NULL) {
393 frame = reqLocalFrame(size,
false);
400 frame = ris::Frame::create();
404 while (alloc < size) {
409 if (fd_ < 0 || fd_ >= FD_SETSIZE)
411 "AxiStreamDma::acceptReq",
412 "fd_=%d outside valid select() range [0, FD_SETSIZE=%d); "
413 "likely causes: instance was stop()'d or never finished construction (fd_<0), "
414 "or process fd table exhausted (fd_>=FD_SETSIZE)",
423 if (select(fd_ + 1, NULL, &fds, NULL, &tout) <= 0) {
424 log_->critical(
"AxiStreamDma::acceptReq: Timeout waiting for outbound buffer after %" PRIuLEAST32
425 ".%" PRIuLEAST32
" seconds! May be caused by outbound back pressure.",
437 buff = createBuffer(desc_->rawBuff[res], 0x80000000 | res, buffSize, desc_->bSize);
438 frame->appendBuffer(buff);
461 if (!desc_ || fd_ < 0)
463 "instance has been stopped or did not finish construction");
470 if (frame->getError()) {
471 log_->warning(
"Dumping errored frame");
476 ris::Frame::BufferIterator it;
477 for (it = frame->beginBuffer(); it != frame->endBuffer(); ++it) {
481 if (it == frame->beginBuffer()) {
482 fuser = frame->getFirstUser();
483 if (enSsi_) fuser |= 0x2;
489 if (it == (frame->endBuffer() - 1)) {
491 luser = frame->getLastUser();
500 meta = (*it)->getMeta();
503 if ((meta & 0x80000000) != 0) {
507 if ((meta & 0x40000000) == 0) {
519 (*it)->setMeta(meta);
528 if (fd_ < 0 || fd_ >= FD_SETSIZE)
530 "AxiStreamDma::acceptFrame",
531 "fd_=%d outside valid select() range [0, FD_SETSIZE=%d); "
532 "likely causes: instance was stop()'d or never finished construction (fd_<0), "
533 "or process fd table exhausted (fd_>=FD_SETSIZE)",
542 if (select(fd_ + 1, NULL, &fds, NULL, &tout) <= 0) {
543 log_->critical(
"AxiStreamDma::acceptFrame: Timeout waiting for outbound write after %" PRIuLEAST32
544 ".%" PRIuLEAST32
" seconds! May be caused by outbound back pressure.",
560 if (emptyFrame) frame->clear();
564void rha::AxiStreamDma::retBuffer(uint8_t* data, uint32_t meta, uint32_t size) {
571 if ((meta & 0x80000000) != 0) {
574 if ((fd_ >= 0) && ((meta & 0x40000000) == 0)) {
576 throw(
rogue::GeneralError(
"AxiStreamDma::retBuffer",
"AXIS Return Buffer Call Failed!!!!"));
582 Pool::retBuffer(data, meta, size);
587void rha::AxiStreamDma::runThread(std::weak_ptr<int> lockPtr) {
589 uint32_t meta[RxBufferCount];
590 uint32_t rxFlags[RxBufferCount];
591 uint32_t rxError[RxBufferCount];
592 int32_t rxSize[RxBufferCount];
608 while (!lockPtr.expired())
continue;
613 frame = ris::Frame::create();
622 if (fd_ < 0 || fd_ >= FD_SETSIZE) {
623 log_->error(
"AxiStreamDma::runThread: fd_ value %d out of FD_SETSIZE range; exiting worker", fd_);
635 if (select(fd_ + 1, &fds, NULL, NULL, &tout) > 0) {
637 if (desc_->rawBuff == NULL) {
639 buff[0] = allocBuffer(desc_->bSize, NULL);
642 rxSize[0] =
dmaRead(fd_, buff[0]->begin(), buff[0]->getAvailable(), rxFlags, rxError, NULL);
651 rxCount =
dmaReadBulkIndex(fd_, RxBufferCount, rxSize, meta, rxFlags, rxError, NULL);
654 for (x = 0; x < rxCount; x++)
655 buff[x] = createBuffer(desc_->rawBuff[meta[x]], 0x80000000 | meta[x], desc_->bSize, desc_->bSize);
659 if (rxCount < 0)
throw(
rogue::GeneralError(
"AxiStreamDma::runThread",
"DMA Interface Failure!"));
662 for (x = 0; x < rxCount; x++) {
667 buff[x]->setPayload(rxSize[x]);
669 error = frame->getError();
672 error |= (rxError[x] & 0xFF);
675 if (frame->isEmpty()) frame->setFirstUser(fuser & 0xFF);
679 frame->setLastUser(luser & 0xFF);
680 if (enSsi_ && ((luser & 0x1) != 0)) error |= 0x80;
683 frame->setError(error);
684 frame->appendBuffer(buff[x]);
690 frame = ris::Frame::create();
698std::string rha::AxiStreamDma::getGitVersion() {
703uint32_t rha::AxiStreamDma::getApiVersion() {
708uint32_t rha::AxiStreamDma::getBuffSize() {
713uint32_t rha::AxiStreamDma::getRxBuffCount() {
718uint32_t rha::AxiStreamDma::getRxBuffinUserCount() {
723uint32_t rha::AxiStreamDma::getRxBuffinHwCount() {
728uint32_t rha::AxiStreamDma::getRxBuffinPreHwQCount() {
733uint32_t rha::AxiStreamDma::getRxBuffinSwQCount() {
738uint32_t rha::AxiStreamDma::getRxBuffMissCount() {
743uint32_t rha::AxiStreamDma::getTxBuffCount() {
748uint32_t rha::AxiStreamDma::getTxBuffinUserCount() {
753uint32_t rha::AxiStreamDma::getTxBuffinHwCount() {
758uint32_t rha::AxiStreamDma::getTxBuffinPreHwQCount() {
763uint32_t rha::AxiStreamDma::getTxBuffinSwQCount() {
768uint32_t rha::AxiStreamDma::getTxBuffMissCount() {
772void rha::AxiStreamDma::setup_python() {
775 bp::class_<rha::AxiStreamDma, rha::AxiStreamDmaPtr, bp::bases<ris::Master, ris::Slave>, boost::noncopyable>(
777 bp::init<std::string, uint32_t, bool>())
778 .def(
"setDriverDebug", &rha::AxiStreamDma::setDriverDebug)
779 .def(
"dmaAck", &rha::AxiStreamDma::dmaAck)
780 .def(
"setTimeout", &rha::AxiStreamDma::setTimeout)
781 .def(
"getGitVersion", &rha::AxiStreamDma::getGitVersion)
782 .def(
"getApiVersion", &rha::AxiStreamDma::getApiVersion)
783 .def(
"getBuffSize", &rha::AxiStreamDma::getBuffSize)
784 .def(
"getRxBuffCount", &rha::AxiStreamDma::getRxBuffCount)
785 .def(
"getRxBuffinUserCount", &rha::AxiStreamDma::getRxBuffinUserCount)
786 .def(
"getRxBuffinHwCount", &rha::AxiStreamDma::getRxBuffinHwCount)
787 .def(
"getRxBuffinPreHwQCount", &rha::AxiStreamDma::getRxBuffinPreHwQCount)
788 .def(
"getRxBuffinSwQCount", &rha::AxiStreamDma::getRxBuffinSwQCount)
789 .def(
"getRxBuffMissCount", &rha::AxiStreamDma::getRxBuffMissCount)
790 .def(
"getTxBuffCount", &rha::AxiStreamDma::getTxBuffCount)
791 .def(
"getTxBuffinUserCount", &rha::AxiStreamDma::getTxBuffinUserCount)
792 .def(
"getTxBuffinHwCount", &rha::AxiStreamDma::getTxBuffinHwCount)
793 .def(
"getTxBuffinPreHwQCount", &rha::AxiStreamDma::getTxBuffinPreHwQCount)
794 .def(
"getTxBuffinSwQCount", &rha::AxiStreamDma::getTxBuffinSwQCount)
795 .def(
"getTxBuffMissCount", &rha::AxiStreamDma::getTxBuffMissCount)
796 .def(
"zeroCopyDisable", &rha::AxiStreamDma::zeroCopyDisable);
798 bp::implicitly_convertible<rha::AxiStreamDmaPtr, ris::MasterPtr>();
799 bp::implicitly_convertible<rha::AxiStreamDmaPtr, ris::SlavePtr>();
static std::mutex sharedBuffersMtx
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.
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.