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
 
Axi4Liteoperator= (const Axi4Lite &)=delete
 
virtual ~Axi4Lite ()
 Destructor.
 

Private Types

typedef ipc::RobustMutex IPCMutex_t
 
typedef std::unique_lock< IPCMutex_tIPCScopedLock_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 ()
 Concrete implementation of the synchronization function to block until all buffers have been sent, all replies received and all data validated.
 
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_tmIPCMutex
 
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 95 of file ProtocolAxi4Lite.hpp.

Member Typedef Documentation

◆ InnerProtocol

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

Definition at line 166 of file ProtocolAxi4Lite.hpp.

◆ IPCMutex_t

◆ IPCScopedLock_t

Definition at line 164 of file ProtocolAxi4Lite.hpp.

◆ SteadyClock_t

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

Definition at line 167 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 191 of file ProtocolAxi4Lite.cpp.

192 : IPbus<2, 0>(aId, aUri),
193 mConnected(false),
194 mMappedFile(getDevicePath(aUri), 64, PROT_WRITE),
197 mMaxInFlight(0),
198 mPageSize(0),
203
204 mSleepDuration = std::chrono::microseconds(50);
205
206 }
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 208 of file ProtocolAxi4Lite.cpp.

208 {
209
210}

Member Function Documentation

◆ connect() [1/2]

void uhallibs::Axi4Lite::connect ( )
private

Set up the connection to the device.

Definition at line 272 of file ProtocolAxi4Lite.cpp.

273{
274 IPCScopedLock_t lLockGuard(*mIPCMutex);
275 connect(lLockGuard);
276}
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 278 of file ProtocolAxi4Lite.cpp.

279{
280 // Read current value of session counter when reading status info from FPGA
281 // (So that can check whether this info is up-to-date later on, when sending next request packet)
283 mIPCSessionCount = mIPCMutex->getCounter();
284
285 log ( uhal::Debug() , "Axi4Lite client is opening device file " , uhal::Quote ( mMappedFile.getPath() ) , " (device-to-client)" );
286
287 // Minimal mapping to read the
290 std::vector<uint32_t> lStats;
291 mMappedFile.read(0, 4, lStats);
293 aGuard.unlock();
294
295 mNumberOfPages = lStats.at(0);
296 if ( (mMaxInFlight == 0) or (mMaxInFlight > mNumberOfPages) )
298 mPageSize = lStats.at(1);
299 if ( (mMaxPacketSize == 0) or (mMaxPacketSize >= mPageSize) )
301 mIndexNextPage = lStats.at(2);
302 mPublishedReplyPageCount = lStats.at(3);
304
305 //
306 constexpr uint32_t lSafetyMargin(4096);
307 // Set the memory mapping range to a value commensurate to the memory available in firmware
310
311 mConnected=true;
312
313 log ( uhal::Info() , "Axi4Lite client connected to device at ", uhal::Quote(mMappedFile.getPath()), ", FPGA has ", Integer(mNumberOfPages), " pages, each of size ", Integer(mPageSize), " words, index ", Integer(mIndexNextPage), " should be filled next" );
314
315}
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 317 of file ProtocolAxi4Lite.cpp.

318{
320 mConnected = false;
321}

◆ dispatchExceptionHandler()

void uhallibs::Axi4Lite::dispatchExceptionHandler ( )
privatevirtual

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

Definition at line 240 of file ProtocolAxi4Lite.cpp.

241{
242 log(uhal::Notice(), "Axi4Lite client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : closing device files since exception detected");
243
244 ClientInterface::returnBufferToPool ( mReplyQueue );
245
247
248 disconnect();
249
250 InnerProtocol::dispatchExceptionHandler();
251}
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:77

◆ 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 227 of file ProtocolAxi4Lite.cpp.

228{
229 log(uhal::Debug(), "Axi4Lite client (URI: ", uhal::Quote(uri()), ") : Flush method called");
230 while ( !mReplyQueue.empty() )
231 read();
232
234
235 IPCScopedLock_t lLockGuard(*mIPCMutex);
236 mIPCMutex->endSession();
237}
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 177 of file ProtocolAxi4Lite.cpp.

177 {
178
179 std::string lPath = aUri.mHostname;
180
181 auto it = std::find_if( aUri.mArguments.begin(), aUri.mArguments.end(),
182 [](const std::pair<std::string, std::string>& element){ return element.first == "dev";} );
183
184 if ( it != aUri.mArguments.end() ) {
185 lPath += "/"+it->second;
186 }
187
188 return lPath;
189}

◆ 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 263 of file ProtocolAxi4Lite.cpp.

264{
265 if ( ! mConnected )
266 connect();
267
268 return mMaxPacketSize * 4;
269}

◆ 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 254 of file ProtocolAxi4Lite.cpp.

255{
256 if ( ! mConnected )
257 connect();
258
259 return mMaxPacketSize * 4;
260}

◆ getSharedMemName()

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

Definition at line 169 of file ProtocolAxi4Lite.cpp.

170{
171 std::string lSanitizedPath(aPath);
172 std::replace(lSanitizedPath.begin(), lSanitizedPath.end(), '/', ':');
173
174 return "/uhal::ipbusaxi4lite-2.0::" + lSanitizedPath;
175}

◆ 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 214 of file ProtocolAxi4Lite.cpp.

215{
216 log(uhal::Debug(), "Axi4Lite client (URI: ", uhal::Quote(uri()), ") : implementDispatch method called");
217
218 if ( ! mConnected )
219 connect();
220
221 if ( mReplyQueue.size() == mMaxInFlight )
222 read();
223 write(aBuffers);
224}
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 355 of file ProtocolAxi4Lite.cpp.

356{
357 const size_t lPageIndexToRead = (mIndexNextPage - mReplyQueue.size() + mNumberOfPages) % mNumberOfPages;
358 SteadyClock_t::time_point lStartTime = SteadyClock_t::now();
359
361 {
362 uint32_t lHwPublishedPageCount = 0x0;
363
364 std::vector<uint32_t> lValues;
365 while ( true ) {
366 // FIXME : Improve by simply adding fileWrite method that takes uint32_t ref as argument (or returns uint32_t)
367 IPCScopedLock_t lGuard(*mIPCMutex);
368 mMappedFile.read(0, 4, lValues);
369 lHwPublishedPageCount = lValues.at(3);
370 log (uhal::Debug(), "Read status info from addr 0 (", Integer(lValues.at(0)), ", ", Integer(lValues.at(1)), ", ", Integer(lValues.at(2)), ", ", Integer(lValues.at(3)), "): ", PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
371
372 if (lHwPublishedPageCount != mPublishedReplyPageCount) {
373 mPublishedReplyPageCount = lHwPublishedPageCount;
374 break;
375 }
376 // FIXME: Throw if published page count is invalid number
377
378 if (SteadyClock_t::now() - lStartTime > std::chrono::microseconds(getBoostTimeoutPeriod().total_microseconds())) {
379 exception::Axi4LiteTimeout lExc;
380 log(lExc, "Next page (index ", Integer(lPageIndexToRead), " count ", Integer(mPublishedReplyPageCount+1), ") of Axi4Lite device '" + mMappedFile.getPath() + "' is not ready after timeout period");
381 throw lExc;
382 }
383
384 log(uhal::Debug(), "Axi4Lite client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : Trying to read page index ", Integer(lPageIndexToRead), " = count ", Integer(mReadReplyPageCount+1), "; published page count is ", Integer(lHwPublishedPageCount), "; sleeping for ", mSleepDuration.count(), "us");
385 if (mSleepDuration > std::chrono::microseconds(0))
386 std::this_thread::sleep_for( mSleepDuration );
387 lValues.clear();
388 }
389
390 log(uhal::Info(), "Axi4Lite client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : Reading page ", Integer(lPageIndexToRead), " (published count ", Integer(lHwPublishedPageCount), ", surpasses required, ", Integer(mReadReplyPageCount + 1), ")");
391
392 }
394
395 // PART 1 : Read the page
396 std::shared_ptr<uhal::Buffers> lBuffers = mReplyQueue.front();
397 mReplyQueue.pop_front();
398
399 uint32_t lNrWordsToRead(lBuffers->replyCounter() >> 2);
400 lNrWordsToRead += 1;
401
402 std::vector<uint32_t> lPageContents;
403 IPCScopedLock_t lGuard(*mIPCMutex);
404 mMappedFile.read(4 + lPageIndexToRead * mPageSize, lNrWordsToRead , lPageContents);
405 lGuard.unlock();
406 log (uhal::Debug(), "Read " , Integer(lNrWordsToRead), " 32-bit words from address " , Integer(4 + lPageIndexToRead * 4 * mPageSize), " ... ", PacketFmt((const uint8_t*)lPageContents.data(), 4 * lPageContents.size()));
407
408 // PART 2 : Transfer to reply buffer
409 const std::deque< std::pair< uint8_t* , uint32_t > >& lReplyBuffers ( lBuffers->getReplyBuffer() );
410 size_t lNrWordsInPacket = (lPageContents.at(0) >> 16) + (lPageContents.at(0) & 0xFFFF);
411 if (lNrWordsInPacket != (lBuffers->replyCounter() >> 2))
412 log (uhal::Warning(), "Expected reply packet to contain ", Integer(lBuffers->replyCounter() >> 2), " words, but it actually contains ", Integer(lNrWordsInPacket), " words");
413
414 size_t lNrBytesCopied = 0;
415 for (const auto& lBuffer: lReplyBuffers)
416 {
417 // Don't copy more of page than was written to, for cases when less data received than expected
418 if ( lNrBytesCopied >= 4*lNrWordsInPacket)
419 break;
420
421 size_t lNrBytesToCopy = std::min( lBuffer.second , uint32_t(4*lNrWordsInPacket - lNrBytesCopied) );
422 memcpy ( lBuffer.first, &lPageContents.at(1 + (lNrBytesCopied / 4)), lNrBytesToCopy );
423 lNrBytesCopied += lNrBytesToCopy;
424 }
425
426
427 // PART 3 : Validate the packet contents
428 uhal::exception::exception* lExc = NULL;
429 try
430 {
431 lExc = ClientInterface::validate ( lBuffers );
432 }
433 catch ( uhal::exception::exception& aExc )
434 {
435 uhal::exception::ValidationError lExc2;
436 log ( lExc2 , "Exception caught during reply validation for Axi4Lite device with URI " , uhal::Quote ( this->uri() ) , "; what returned: " , uhal::Quote ( aExc.what() ) );
437 throw lExc2;
438 }
439
440 if (lExc != NULL)
441 lExc->throwAsDerivedType();
442}

◆ 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 323 of file ProtocolAxi4Lite.cpp.

324{
325 if (not mMappedFile.haveLock()) {
327
328 IPCScopedLock_t lGuard(*mIPCMutex);
329 mIPCMutex->startSession();
331
332 // If these two numbers don't match, another client/process has sent packets
333 // more recently than this client has, so must re-read status info
334 if (mIPCExternalSessionActive or (mIPCMutex->getCounter() != mIPCSessionCount)) {
335 connect(lGuard);
336 }
337 }
338
339 log (uhal::Info(), "Axi4Lite client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : writing ", Integer(aBuffers->sendCounter() / 4), "-word packet to page ", Integer(mIndexNextPage), " in ", uhal::Quote(mMappedFile.getPath()));
340
341 const uint32_t lHeaderWord = (0x10000 | (((aBuffers->sendCounter() / 4) - 1) & 0xFFFF));
342 std::vector<std::pair<const uint8_t*, size_t> > lDataToWrite;
343 lDataToWrite.push_back( std::make_pair(reinterpret_cast<const uint8_t*>(&lHeaderWord), sizeof lHeaderWord) );
344 lDataToWrite.push_back( std::make_pair(aBuffers->getSendBuffer(), aBuffers->sendCounter()) );
345
346 IPCScopedLock_t lGuard(*mIPCMutex);
347 mMappedFile.write(mIndexNextPage * mPageSize, lDataToWrite);
348 log (uhal::Debug(), "Wrote " , Integer((aBuffers->sendCounter() / 4) + 1), " 32-bit words at address " , Integer(mIndexNextPage * mPageSize), " ... ", PacketFmt(lDataToWrite));
349
351 mReplyQueue.push_back(aBuffers);
352}
void write(const uint32_t aAddr, const std::vector< uint32_t > &aValues)

Member Data Documentation

◆ mConnected

bool uhallibs::Axi4Lite::mConnected
private

Definition at line 212 of file ProtocolAxi4Lite.hpp.

◆ mIndexNextPage

uint32_t uhallibs::Axi4Lite::mIndexNextPage
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mIPCExternalSessionActive

bool uhallibs::Axi4Lite::mIPCExternalSessionActive
private

Definition at line 217 of file ProtocolAxi4Lite.hpp.

◆ mIPCMutex

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

Definition at line 216 of file ProtocolAxi4Lite.hpp.

◆ mIPCSessionCount

uint64_t uhallibs::Axi4Lite::mIPCSessionCount
private

Definition at line 218 of file ProtocolAxi4Lite.hpp.

◆ mMappedFile

MappedFile uhallibs::Axi4Lite::mMappedFile
private

Definition at line 214 of file ProtocolAxi4Lite.hpp.

◆ mMaxInFlight

uint32_t uhallibs::Axi4Lite::mMaxInFlight
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mMaxPacketSize

uint32_t uhallibs::Axi4Lite::mMaxPacketSize
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mNumberOfPages

uint32_t uhallibs::Axi4Lite::mNumberOfPages
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mPageSize

uint32_t uhallibs::Axi4Lite::mPageSize
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mPublishedReplyPageCount

uint32_t uhallibs::Axi4Lite::mPublishedReplyPageCount
private

Definition at line 222 of file ProtocolAxi4Lite.hpp.

◆ mReadReplyPageCount

uint32_t uhallibs::Axi4Lite::mReadReplyPageCount
private

Definition at line 222 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 225 of file ProtocolAxi4Lite.hpp.

◆ mSleepDuration

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

Definition at line 220 of file ProtocolAxi4Lite.hpp.


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