DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
uhallibs::Axi4Lite Class Reference

Transport protocol to transfer an IPbus buffer over Axi4Lite mapped in a 32b address space. More...

#include <ProtocolAxi4Lite.hpp>

Inheritance diagram for uhallibs::Axi4Lite:
[legend]
Collaboration diagram for uhallibs::Axi4Lite:
[legend]

Classes

class  MappedFile

Public Member Functions

 Axi4Lite (const std::string &aId, const uhal::URI &aUri)
 Axi4Lite (const Axi4Lite &)=delete
Axi4Lite & operator= (const Axi4Lite &)=delete
virtual ~Axi4Lite ()
 Destructor.

Private Types

typedef ipc::RobustMutex IPCMutex_t
typedef std::unique_lock< IPCMutex_t > IPCScopedLock_t
typedef IPbus< 2, 0 > InnerProtocol
typedef std::chrono::steady_clock SteadyClock_t

Private Member Functions

void implementDispatch (std::shared_ptr< uhal::Buffers > aBuffers)
virtual void Flush ()
virtual void dispatchExceptionHandler ()
 Function which tidies up this protocol layer in the event of an exception.
uint32_t getMaxSendSize ()
uint32_t getMaxReplySize ()
void connect ()
 Set up the connection to the device.
void connect (IPCScopedLock_t &)
 Set up the connection to the device.
void disconnect ()
 Close the connection to the device.
void write (const std::shared_ptr< uhal::Buffers > &aBuffers)
 Write request packet to next page in host-to-FPGA device file.
void read ()
 Read next pending reply packet from appropriate page of FPGA-to-host device file, and validate contents.

Static Private Member Functions

static std::string getDevicePath (const uhal::URI &aUri)
static std::string getSharedMemName (const std::string &)

Private Attributes

bool mConnected
MappedFile mMappedFile
ipc::SharedMemObject< IPCMutex_t > mIPCMutex
bool mIPCExternalSessionActive
uint64_t mIPCSessionCount
std::chrono::microseconds mSleepDuration
uint32_t mNumberOfPages
uint32_t mMaxInFlight
uint32_t mPageSize
uint32_t mMaxPacketSize
uint32_t mIndexNextPage
uint32_t mPublishedReplyPageCount
uint32_t mReadReplyPageCount
std::deque< std::shared_ptr< uhal::Buffers > > mReplyQueue
 The list of buffers still awaiting a reply.

Detailed Description

Transport protocol to transfer an IPbus buffer over Axi4Lite mapped in a 32b address space.

Definition at line 92 of file ProtocolAxi4Lite.hpp.

Member Typedef Documentation

◆ InnerProtocol

typedef IPbus<2, 0> uhallibs::Axi4Lite::InnerProtocol
private

Definition at line 157 of file ProtocolAxi4Lite.hpp.

◆ IPCMutex_t

Definition at line 154 of file ProtocolAxi4Lite.hpp.

◆ IPCScopedLock_t

typedef std::unique_lock<IPCMutex_t> uhallibs::Axi4Lite::IPCScopedLock_t
private

Definition at line 155 of file ProtocolAxi4Lite.hpp.

◆ SteadyClock_t

typedef std::chrono::steady_clock uhallibs::Axi4Lite::SteadyClock_t
private

Definition at line 158 of file ProtocolAxi4Lite.hpp.

Constructor & Destructor Documentation

◆ Axi4Lite() [1/2]

uhallibs::Axi4Lite::Axi4Lite ( const std::string & aId,
const uhal::URI & aUri )

Constructor

Parameters
aIdthe uinique identifier that the client will be given.
aUria struct containing the full URI of the target.

Definition at line 247 of file ProtocolAxi4Lite.cpp.

248 : IPbus<2, 0>(aId, aUri)
249 , mConnected(false)
250 , mMappedFile(getDevicePath(aUri), 64, PROT_WRITE)
252 , mNumberOfPages(0)
253 , mMaxInFlight(0)
254 , mPageSize(0)
255 , mMaxPacketSize(0)
256 , mIndexNextPage(0)
259{
260
261 mSleepDuration = std::chrono::microseconds(50);
262}
const std::string & getPath() const
std::chrono::microseconds mSleepDuration
static std::string getSharedMemName(const std::string &)
ipc::SharedMemObject< IPCMutex_t > mIPCMutex
static std::string getDevicePath(const uhal::URI &aUri)

◆ Axi4Lite() [2/2]

uhallibs::Axi4Lite::Axi4Lite ( const Axi4Lite & )
delete

◆ ~Axi4Lite()

uhallibs::Axi4Lite::~Axi4Lite ( )
virtual

Destructor.

Definition at line 264 of file ProtocolAxi4Lite.cpp.

264{}

Member Function Documentation

◆ connect() [1/2]

void uhallibs::Axi4Lite::connect ( )
private

Set up the connection to the device.

Definition at line 330 of file ProtocolAxi4Lite.cpp.

331{
332 IPCScopedLock_t lLockGuard(*mIPCMutex);
333 connect(lLockGuard);
334}
void connect()
Set up the connection to the device.
std::unique_lock< IPCMutex_t > IPCScopedLock_t

◆ connect() [2/2]

void uhallibs::Axi4Lite::connect ( IPCScopedLock_t & aGuard)
private

Set up the connection to the device.

Definition at line 337 of file ProtocolAxi4Lite.cpp.

338{
339 // Read current value of session counter when reading status info from FPGA
340 // (So that can check whether this info is up-to-date later on, when sending next request packet)
342 mIPCSessionCount = mIPCMutex->getCounter();
343
344 log(uhal::Debug(),
345 "Axi4Lite client is opening device file ",
346 uhal::Quote(mMappedFile.getPath()),
347 " (device-to-client)");
348
349 // Minimal mapping to read the
352 std::vector<uint32_t> lStats;
353 mMappedFile.read(0, 4, lStats);
355 aGuard.unlock();
356
357 mNumberOfPages = lStats.at(0);
358 if ((mMaxInFlight == 0) or (mMaxInFlight > mNumberOfPages))
360 mPageSize = lStats.at(1);
361 if ((mMaxPacketSize == 0) or (mMaxPacketSize >= mPageSize))
363 mIndexNextPage = lStats.at(2);
364 mPublishedReplyPageCount = lStats.at(3);
366
367 //
368 constexpr uint32_t lSafetyMargin(4096);
369 // Set the memory mapping range to a value commensurate to the memory available in firmware
370 mMappedFile.setLength(mNumberOfPages * mPageSize + 4 + lSafetyMargin);
372
373 mConnected = true;
374
375 log(uhal::Info(),
376 "Axi4Lite client connected to device at ",
377 uhal::Quote(mMappedFile.getPath()),
378 ", FPGA has ",
379 Integer(mNumberOfPages),
380 " pages, each of size ",
381 Integer(mPageSize),
382 " words, index ",
383 Integer(mIndexNextPage),
384 " should be filled next");
385}
void close()
Unmap and close file.
void open()
Open bus file and map it to memory.
void read(const uint32_t aAddr, const uint32_t aNrWords, std::vector< uint32_t > &aValues)

◆ disconnect()

void uhallibs::Axi4Lite::disconnect ( )
private

Close the connection to the device.

Definition at line 388 of file ProtocolAxi4Lite.cpp.

389{
391 mConnected = false;
392}

◆ dispatchExceptionHandler()

void uhallibs::Axi4Lite::dispatchExceptionHandler ( )
privatevirtual

Function which tidies up this protocol layer in the event of an exception.

Definition at line 293 of file ProtocolAxi4Lite.cpp.

294{
295 log(uhal::Notice(),
296 "Axi4Lite client ",
297 uhal::Quote(id()),
298 " (URI: ",
299 uhal::Quote(uri()),
300 ") : closing device files since exception detected");
301
302 ClientInterface::returnBufferToPool(mReplyQueue);
303
305
306 disconnect();
307
308 InnerProtocol::dispatchExceptionHandler();
309}
std::deque< std::shared_ptr< uhal::Buffers > > mReplyQueue
The list of buffers still awaiting a reply.
void disconnect()
Close the connection to the device.
Unsupported std::string uri Execution of command std::string error Failed to create CommandFacility uri
Definition Issues.hpp:71

◆ Flush()

void uhallibs::Axi4Lite::Flush ( )
privatevirtual

Concrete implementation of the synchronization function to block until all buffers have been sent, all replies received and all data validated

Definition at line 280 of file ProtocolAxi4Lite.cpp.

281{
282 log(uhal::Debug(), "Axi4Lite client (URI: ", uhal::Quote(uri()), ") : Flush method called");
283 while (!mReplyQueue.empty())
284 read();
285
287
288 IPCScopedLock_t lLockGuard(*mIPCMutex);
289 mIPCMutex->endSession();
290}
void read()
Read next pending reply packet from appropriate page of FPGA-to-host device file, and validate conten...

◆ getDevicePath()

std::string uhallibs::Axi4Lite::getDevicePath ( const uhal::URI & aUri)
staticprivate

Definition at line 231 of file ProtocolAxi4Lite.cpp.

232{
233
234 std::string lPath = aUri.mHostname;
235
236 auto it = std::find_if(aUri.mArguments.begin(),
237 aUri.mArguments.end(),
238 [](const std::pair<std::string, std::string>& element) { return element.first == "dev"; });
239
240 if (it != aUri.mArguments.end()) {
241 lPath += "/" + it->second;
242 }
243
244 return lPath;
245}

◆ getMaxReplySize()

uint32_t uhallibs::Axi4Lite::getMaxReplySize ( )
private

Return the maximum size of reply packet based on the buffer size in the target

Returns
the maximum size of reply packet

Definition at line 321 of file ProtocolAxi4Lite.cpp.

322{
323 if (!mConnected)
324 connect();
325
326 return mMaxPacketSize * 4;
327}

◆ getMaxSendSize()

uint32_t uhallibs::Axi4Lite::getMaxSendSize ( )
private

Return the maximum size to be sent based on the buffer size in the target

Returns
the maximum size to be sent

Definition at line 312 of file ProtocolAxi4Lite.cpp.

313{
314 if (!mConnected)
315 connect();
316
317 return mMaxPacketSize * 4;
318}

◆ getSharedMemName()

std::string uhallibs::Axi4Lite::getSharedMemName ( const std::string & aPath)
staticprivate

Definition at line 222 of file ProtocolAxi4Lite.cpp.

223{
224 std::string lSanitizedPath(aPath);
225 std::replace(lSanitizedPath.begin(), lSanitizedPath.end(), '/', ':');
226
227 return "/uhal::ipbusaxi4lite-2.0::" + lSanitizedPath;
228}

◆ implementDispatch()

void uhallibs::Axi4Lite::implementDispatch ( std::shared_ptr< uhal::Buffers > aBuffers)
private

Send the IPbus buffer to the target, read back the response and call the packing-protocol's validate function

Parameters
aBuffersthe buffer object wrapping the send and recieve buffers that are to be transported If multithreaded, adds buffer to the dispatch queue and returns. If single-threaded, calls the dispatch-worker dispatch function directly and blocks until the response is validated.

Definition at line 267 of file ProtocolAxi4Lite.cpp.

268{
269 log(uhal::Debug(), "Axi4Lite client (URI: ", uhal::Quote(uri()), ") : implementDispatch method called");
270
271 if (!mConnected)
272 connect();
273
274 if (mReplyQueue.size() == mMaxInFlight)
275 read();
276 write(aBuffers);
277}
void write(const std::shared_ptr< uhal::Buffers > &aBuffers)
Write request packet to next page in host-to-FPGA device file.

◆ operator=()

Axi4Lite & uhallibs::Axi4Lite::operator= ( const Axi4Lite & )
delete

◆ read()

void uhallibs::Axi4Lite::read ( )
private

Read next pending reply packet from appropriate page of FPGA-to-host device file, and validate contents.

Definition at line 443 of file ProtocolAxi4Lite.cpp.

444{
445 const size_t lPageIndexToRead = (mIndexNextPage - mReplyQueue.size() + mNumberOfPages) % mNumberOfPages;
446 SteadyClock_t::time_point lStartTime = SteadyClock_t::now();
447
449 uint32_t lHwPublishedPageCount = 0x0;
450
451 std::vector<uint32_t> lValues;
452 while (true) {
453 // FIXME : Improve by simply adding fileWrite method that takes uint32_t ref as argument (or returns uint32_t)
454 IPCScopedLock_t lGuard(*mIPCMutex);
455 mMappedFile.read(0, 4, lValues);
456 lHwPublishedPageCount = lValues.at(3);
457 log(uhal::Debug(),
458 "Read status info from addr 0 (",
459 Integer(lValues.at(0)),
460 ", ",
461 Integer(lValues.at(1)),
462 ", ",
463 Integer(lValues.at(2)),
464 ", ",
465 Integer(lValues.at(3)),
466 "): ",
467 PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
468
469 if (lHwPublishedPageCount != mPublishedReplyPageCount) {
470 mPublishedReplyPageCount = lHwPublishedPageCount;
471 break;
472 }
473 // FIXME: Throw if published page count is invalid number
474
475 if (SteadyClock_t::now() - lStartTime > std::chrono::microseconds(getBoostTimeoutPeriod().total_microseconds())) {
476 exception::Axi4LiteTimeout lExc;
477 log(lExc,
478 "Next page (index ",
479 Integer(lPageIndexToRead),
480 " count ",
481 Integer(mPublishedReplyPageCount + 1),
482 ") of Axi4Lite device '" + mMappedFile.getPath() + "' is not ready after timeout period");
483 throw lExc;
484 }
485
486 log(uhal::Debug(),
487 "Axi4Lite client ",
488 uhal::Quote(id()),
489 " (URI: ",
490 uhal::Quote(uri()),
491 ") : Trying to read page index ",
492 Integer(lPageIndexToRead),
493 " = count ",
494 Integer(mReadReplyPageCount + 1),
495 "; published page count is ",
496 Integer(lHwPublishedPageCount),
497 "; sleeping for ",
498 mSleepDuration.count(),
499 "us");
500 if (mSleepDuration > std::chrono::microseconds(0))
501 std::this_thread::sleep_for(mSleepDuration);
502 lValues.clear();
503 }
504
505 log(uhal::Info(),
506 "Axi4Lite client ",
507 uhal::Quote(id()),
508 " (URI: ",
509 uhal::Quote(uri()),
510 ") : Reading page ",
511 Integer(lPageIndexToRead),
512 " (published count ",
513 Integer(lHwPublishedPageCount),
514 ", surpasses required, ",
515 Integer(mReadReplyPageCount + 1),
516 ")");
517 }
519
520 // PART 1 : Read the page
521 std::shared_ptr<uhal::Buffers> lBuffers = mReplyQueue.front();
522 mReplyQueue.pop_front();
523
524 uint32_t lNrWordsToRead(lBuffers->replyCounter() >> 2);
525 lNrWordsToRead += 1;
526
527 std::vector<uint32_t> lPageContents;
528 IPCScopedLock_t lGuard(*mIPCMutex);
529 mMappedFile.read(4 + lPageIndexToRead * mPageSize, lNrWordsToRead, lPageContents);
530 lGuard.unlock();
531 log(uhal::Debug(),
532 "Read ",
533 Integer(lNrWordsToRead),
534 " 32-bit words from address ",
535 Integer(4 + lPageIndexToRead * 4 * mPageSize),
536 " ... ",
537 PacketFmt((const uint8_t*)lPageContents.data(), 4 * lPageContents.size()));
538
539 // PART 2 : Transfer to reply buffer
540 const std::deque<std::pair<uint8_t*, uint32_t>>& lReplyBuffers(lBuffers->getReplyBuffer());
541 size_t lNrWordsInPacket = (lPageContents.at(0) >> 16) + (lPageContents.at(0) & 0xFFFF);
542 if (lNrWordsInPacket != (lBuffers->replyCounter() >> 2))
543 log(uhal::Warning(),
544 "Expected reply packet to contain ",
545 Integer(lBuffers->replyCounter() >> 2),
546 " words, but it actually contains ",
547 Integer(lNrWordsInPacket),
548 " words");
549
550 size_t lNrBytesCopied = 0;
551 for (const auto& lBuffer : lReplyBuffers) {
552 // Don't copy more of page than was written to, for cases when less data received than expected
553 if (lNrBytesCopied >= 4 * lNrWordsInPacket)
554 break;
555
556 size_t lNrBytesToCopy = std::min(lBuffer.second, uint32_t(4 * lNrWordsInPacket - lNrBytesCopied));
557 memcpy(lBuffer.first, &lPageContents.at(1 + (lNrBytesCopied / 4)), lNrBytesToCopy);
558 lNrBytesCopied += lNrBytesToCopy;
559 }
560
561 // PART 3 : Validate the packet contents
562 uhal::exception::exception* lExc = NULL;
563 try {
564 lExc = ClientInterface::validate(lBuffers);
565 } catch (uhal::exception::exception& aExc) {
566 uhal::exception::ValidationError lExc2;
567 log(lExc2,
568 "Exception caught during reply validation for Axi4Lite device with URI ",
569 uhal::Quote(this->uri()),
570 "; what returned: ",
571 uhal::Quote(aExc.what()));
572 throw lExc2;
573 }
574
575 if (lExc != NULL)
576 lExc->throwAsDerivedType();
577}
PacketFmt(const uint8_t *const, const size_t)
Definition formatters.cpp:7

◆ write()

void uhallibs::Axi4Lite::write ( const std::shared_ptr< uhal::Buffers > & aBuffers)
private

Write request packet to next page in host-to-FPGA device file.

Definition at line 395 of file ProtocolAxi4Lite.cpp.

396{
397 if (not mMappedFile.haveLock()) {
399
400 IPCScopedLock_t lGuard(*mIPCMutex);
401 mIPCMutex->startSession();
403
404 // If these two numbers don't match, another client/process has sent packets
405 // more recently than this client has, so must re-read status info
406 if (mIPCExternalSessionActive or (mIPCMutex->getCounter() != mIPCSessionCount)) {
407 connect(lGuard);
408 }
409 }
410
411 log(uhal::Info(),
412 "Axi4Lite client ",
413 uhal::Quote(id()),
414 " (URI: ",
415 uhal::Quote(uri()),
416 ") : writing ",
417 Integer(aBuffers->sendCounter() / 4),
418 "-word packet to page ",
419 Integer(mIndexNextPage),
420 " in ",
421 uhal::Quote(mMappedFile.getPath()));
422
423 const uint32_t lHeaderWord = (0x10000 | (((aBuffers->sendCounter() / 4) - 1) & 0xFFFF));
424 std::vector<std::pair<const uint8_t*, size_t>> lDataToWrite;
425 lDataToWrite.push_back(std::make_pair(reinterpret_cast<const uint8_t*>(&lHeaderWord), sizeof lHeaderWord));
426 lDataToWrite.push_back(std::make_pair(aBuffers->getSendBuffer(), aBuffers->sendCounter()));
427
428 IPCScopedLock_t lGuard(*mIPCMutex);
429 mMappedFile.write(mIndexNextPage * mPageSize, lDataToWrite);
430 log(uhal::Debug(),
431 "Wrote ",
432 Integer((aBuffers->sendCounter() / 4) + 1),
433 " 32-bit words at address ",
434 Integer(mIndexNextPage * mPageSize),
435 " ... ",
436 PacketFmt(lDataToWrite));
437
439 mReplyQueue.push_back(aBuffers);
440}
void write(const uint32_t aAddr, const std::vector< uint32_t > &aValues)

Member Data Documentation

◆ mConnected

bool uhallibs::Axi4Lite::mConnected
private

Definition at line 205 of file ProtocolAxi4Lite.hpp.

◆ mIndexNextPage

uint32_t uhallibs::Axi4Lite::mIndexNextPage
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mIPCExternalSessionActive

bool uhallibs::Axi4Lite::mIPCExternalSessionActive
private

Definition at line 210 of file ProtocolAxi4Lite.hpp.

◆ mIPCMutex

ipc::SharedMemObject<IPCMutex_t> uhallibs::Axi4Lite::mIPCMutex
private

Definition at line 209 of file ProtocolAxi4Lite.hpp.

◆ mIPCSessionCount

uint64_t uhallibs::Axi4Lite::mIPCSessionCount
private

Definition at line 211 of file ProtocolAxi4Lite.hpp.

◆ mMappedFile

MappedFile uhallibs::Axi4Lite::mMappedFile
private

Definition at line 207 of file ProtocolAxi4Lite.hpp.

◆ mMaxInFlight

uint32_t uhallibs::Axi4Lite::mMaxInFlight
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mMaxPacketSize

uint32_t uhallibs::Axi4Lite::mMaxPacketSize
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mNumberOfPages

uint32_t uhallibs::Axi4Lite::mNumberOfPages
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mPageSize

uint32_t uhallibs::Axi4Lite::mPageSize
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mPublishedReplyPageCount

uint32_t uhallibs::Axi4Lite::mPublishedReplyPageCount
private

Definition at line 215 of file ProtocolAxi4Lite.hpp.

◆ mReadReplyPageCount

uint32_t uhallibs::Axi4Lite::mReadReplyPageCount
private

Definition at line 216 of file ProtocolAxi4Lite.hpp.

◆ mReplyQueue

std::deque<std::shared_ptr<uhal::Buffers> > uhallibs::Axi4Lite::mReplyQueue
private

The list of buffers still awaiting a reply.

Definition at line 219 of file ProtocolAxi4Lite.hpp.

◆ mSleepDuration

std::chrono::microseconds uhallibs::Axi4Lite::mSleepDuration
private

Definition at line 213 of file ProtocolAxi4Lite.hpp.


The documentation for this class was generated from the following files: