@@ -93,22 +93,26 @@ CrorcDmaChannel::~CrorcDmaChannel()
9393
9494void CrorcDmaChannel::deviceStartDma ()
9595{
96- // With the C-RORC, we can't start DMA until we have enough memory to cover 128 DMA pages (which should be covered by
97- // 1 superpage). So we set the "pending DMA start" state and actually start once a superpage has been pushed.
98- log (" DMA start deferred until superpage available" );
96+ log (" DMA start deferred until enough superpages available" );
9997
10098 mFifoBack = 0 ;
10199 mFifoSize = 0 ;
102- mSuperpageQueue .clear ();
100+ mReadyQueue .clear ();
101+ mTransferQueue .clear ();
103102 mPendingDmaStart = true ;
104103}
105104
106- void CrorcDmaChannel::startPendingDma (SuperpageQueueEntry& entry )
105+ void CrorcDmaChannel::startPendingDma ()
107106{
108107 if (!mPendingDmaStart ) {
109108 return ;
110109 }
111110
111+ if (mTransferQueue .size () < DMA_START_REQUIRED_SUPERPAGES) {
112+ log (" Insufficient superpages to start pending DMA" );
113+ return ;
114+ }
115+
112116 log (" Starting pending DMA" );
113117
114118 if (mUseContinuousReadout ) {
@@ -126,15 +130,11 @@ void CrorcDmaChannel::startPendingDma(SuperpageQueueEntry& entry)
126130 startDataReceiving ();
127131
128132 // Initializing the firmware FIFO, pushing (entries) pages
129- for (int i = 0 ; i < READYFIFO_ENTRIES ; ++i){
133+ for (size_t i = 0 ; i < DMA_START_REQUIRED_SUPERPAGES ; ++i){
130134 getReadyFifoUser ()->entries [i].reset ();
131- pushIntoSuperpage (entry);
132- }
133-
134- assert (entry.pushedPages <= entry.maxPages );
135- if (entry.pushedPages == entry.maxPages ) {
136- // Remove superpage from pushing queue
137- mSuperpageQueue .removeFromPushingQueue ();
135+ auto superpage = mTransferQueue [i];
136+ mReadyQueue .push_back ();
137+ pushFreeFifoPage (i, getBusOffsetAddress (superpage.getOffset ()));
138138 }
139139
140140 if (mGeneratorEnabled ) {
@@ -161,11 +161,10 @@ void CrorcDmaChannel::startPendingDma(SuperpageQueueEntry& entry)
161161 log (" Initial pages not arrived" , InfoLogger::InfoLogger::Warning);
162162 }
163163
164- entry.superpage .setReceived (entry.superpage .getReceived () + READYFIFO_ENTRIES * mPageSize );
165-
166- if (entry.superpage .getReceived () == entry.superpage .getSize ()) {
167- entry.superpage .setReady (true );
168- mSuperpageQueue .moveFromArrivalsToFilledQueue ();
164+ for (size_t i = 0 ; i < DMA_START_REQUIRED_SUPERPAGES; ++i){
165+ auto superpage = mTransferQueue .front ();
166+ mReadyQueue .push_back (superpage);
167+ mTransferQueue .pop_front ();
169168 }
170169
171170 getReadyFifoUser ()->reset ();
@@ -174,11 +173,6 @@ void CrorcDmaChannel::startPendingDma(SuperpageQueueEntry& entry)
174173
175174 mPendingDmaStart = false ;
176175 log (" DMA started" );
177-
178- if (mUseContinuousReadout ) {
179- log (" Starting continuous readout" );
180- Crorc::Crorc::startReadoutContinuous (*(getBar ()));
181- }
182176}
183177
184178void CrorcDmaChannel::deviceStopDma ()
@@ -283,109 +277,92 @@ void CrorcDmaChannel::startDataReceiving()
283277
284278int CrorcDmaChannel::getTransferQueueAvailable ()
285279{
286- return mSuperpageQueue . getQueueAvailable ();
280+ return TRANSFER_QUEUE_CAPACITY - mTransferQueue . size ();
287281}
288282
289283int CrorcDmaChannel::getReadyQueueSize ()
290284{
291- return mSuperpageQueue . getFilled () .size ();
285+ return mReadyQueue .size ();
292286}
293287
294288auto CrorcDmaChannel::getSuperpage () -> Superpage
295289{
296- return mSuperpageQueue .getFrontSuperpage ();
290+ if (mReadyQueue .empty ()) {
291+ BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not get superpage, ready queue was empty" ));
292+ }
293+ return mReadyQueue .front ();
297294}
298295
299296void CrorcDmaChannel::pushSuperpage (Superpage superpage)
300297{
301298 checkSuperpage (superpage);
302299 constexpr size_t MIN_SIZE = 1 *1024 *1024 ;
300+ constexpr size_t MAX_SIZE = 2 *1024 *1024 ;
301+
302+ if (superpage.getSize () > MAX_SIZE) {
303+ BOOST_THROW_EXCEPTION (CrorcException ()
304+ << ErrorInfo::Message (" Could not enqueue superpage, C-RORC backend does not support superpage sizes above 2 MiB" ));
305+ }
303306
304307 if (!Utilities::isMultiple (superpage.getSize (), MIN_SIZE)) {
305308 BOOST_THROW_EXCEPTION (CrorcException ()
306- << ErrorInfo::Message (" Could not enqueue superpage, C-RORC backend requires superpage size multiple of 1 MiB" ));
307- // We require 1 MiB because this fits 128 8KiB DMA pages (see deviceStartDma() for why we need that)
309+ << ErrorInfo::Message (" Could not enqueue superpage, C-RORC backend requires superpage size multiple of 1 MiB" ));
308310 }
309311
310- SuperpageQueueEntry entry;
311- entry.busAddress = getBusOffsetAddress (superpage.getOffset ());
312- entry.maxPages = superpage.getSize () / mPageSize ;
313- entry.pushedPages = 0 ;
314- entry.superpage = superpage;
315- entry.superpage .setReceived (0 );
312+ if (mTransferQueue .size () >= TRANSFER_QUEUE_CAPACITY) {
313+ BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not push superpage, transfer queue was full" ));
314+ }
316315
317- mSuperpageQueue .addToQueue (entry);
316+ if (mFifoSize >= READYFIFO_ENTRIES) {
317+ BOOST_THROW_EXCEPTION (Exception ()
318+ << ErrorInfo::Message (" Could not push superpage, firmware queue was full (this should never happen)" ));
319+ }
320+
321+ mTransferQueue .push_back (superpage);
322+ auto busAddress = getBusOffsetAddress (superpage.getOffset ());
323+ pushFreeFifoPage (getFifoFront (), busAddress);
324+ mFifoSize ++;
318325}
319326
320327auto CrorcDmaChannel::popSuperpage () -> Superpage
321328{
322- return mSuperpageQueue .removeFromFilledQueue ().superpage ;
329+ if (mReadyQueue .empty ()) {
330+ BOOST_THROW_EXCEPTION (Exception () << ErrorInfo::Message (" Could not pop superpage, ready queue was empty" ));
331+ }
332+ auto superpage = mReadyQueue .front ();
333+ mReadyQueue .pop_front ();
334+ return superpage;
323335}
324336
325337void CrorcDmaChannel::fillSuperpages ()
326338{
327- // Push new pages into superpage
328- if (!mSuperpageQueue .getPushing ().empty ()) {
329- SuperpageQueueEntry& entry = mSuperpageQueue .getPushingFrontEntry ();
330-
331- if (mPendingDmaStart ) {
332- // Do some special handling of first transfers......
333- startPendingDma (entry);
339+ if (mPendingDmaStart ) {
340+ if (mTransferQueue .size () >= DMA_START_REQUIRED_SUPERPAGES) {
341+ startPendingDma ();
334342 } else {
335- int freeDescriptors = FIFO_QUEUE_MAX - mFifoSize ;
336- int freePages = entry.getUnpushedPages ();
337- int possibleToPush = std::min (freeDescriptors, freePages);
338-
339- for (int i = 0 ; i < possibleToPush; ++i) {
340- pushIntoSuperpage (entry);
341- }
342-
343- if (entry.isPushed ()) {
344- // Remove superpage from pushing queue
345- mSuperpageQueue .removeFromPushingQueue ();
346- }
343+ // Waiting on enough superpages to start DMA...
344+ return ;
347345 }
348346 }
349347
350348 // Check for arrivals & handle them
351- if (!mSuperpageQueue . getArrivals () .empty ()) {
349+ if (!mTransferQueue .empty ()) {
352350 auto isArrived = [&](int descriptorIndex) {return dataArrived (descriptorIndex) == DataArrivalStatus::WholeArrived;};
353351 auto resetDescriptor = [&](int descriptorIndex) {getReadyFifoUser ()->entries [descriptorIndex].reset ();};
354352
355353 while (mFifoSize > 0 ) {
356- SuperpageQueueEntry& entry = mSuperpageQueue .getArrivalsFrontEntry ();
357-
358354 if (isArrived (mFifoBack )) {
359- // XXX Dirty hack for now: write length field into page SDH. In upcoming firmwares, the card will do this
360- // itself
361- auto writeSdhEventSize = [](uintptr_t pageAddress, uint32_t eventSize){
362- constexpr size_t OFFSET_SDH_EVENT_SIZE = 16 ; // 1 * 128b word
363- // auto address = reinterpret_cast<char*>(pageAddress + OFFSET_SDH_EVENT_SIZE);
364- // // Clear first 3 32b values of event size word
365- // memset(address, 0, sizeof(uint32_t) * 3);
366- // // Write to 4th 32b value of event size word
367- // memcpy(address + (sizeof(uint32_t) * 3), &eventSize, sizeof(uint32_t));
368- auto address = reinterpret_cast <volatile uint32_t *>(pageAddress + OFFSET_SDH_EVENT_SIZE);
369- address[0 ] = 0 ;
370- address[1 ] = 0 ;
371- address[2 ] = 0 ;
372- address[3 ] = eventSize;
373- };
374-
375355 uint32_t length = getReadyFifoUser ()->entries [mFifoBack ].getSize ();
376- auto pageAddress = mDmaBufferUserspace + entry.superpage .getOffset () + entry.superpage .getReceived ();
377- writeSdhEventSize (pageAddress, length);
378-
379356 resetDescriptor (mFifoBack );
357+
380358 mFifoSize --;
381359 mFifoBack = (mFifoBack + 1 ) % READYFIFO_ENTRIES;
382- entry.superpage .setReceived (entry.superpage .getReceived () + mPageSize );
383360
384- if (entry. superpage . isFilled ()) {
385- // Move superpage to filled queue
386- entry. superpage .setReady (true );
387- mSuperpageQueue . moveFromArrivalsToFilledQueue ( );
388- }
361+ auto superpage = mTransferQueue . front ();
362+ superpage. setReceived (length);
363+ superpage.setReady (true );
364+ mReadyQueue . push_back (superpage );
365+ mTransferQueue . pop_front ();
389366 } else {
390367 // If the back one hasn't arrived yet, the next ones will certainly not have arrived either...
391368 break ;
@@ -394,23 +371,6 @@ void CrorcDmaChannel::fillSuperpages()
394371 }
395372}
396373
397- void CrorcDmaChannel::pushIntoSuperpage (SuperpageQueueEntry& entry)
398- {
399- assert (mFifoSize < FIFO_QUEUE_MAX);
400- assert (entry.pushedPages < entry.maxPages );
401-
402- pushFreeFifoPage (getFifoFront (), getNextSuperpageBusAddress (entry));
403- mFifoSize ++;
404- entry.pushedPages ++;
405- }
406-
407- uintptr_t CrorcDmaChannel::getNextSuperpageBusAddress (const SuperpageQueueEntry& entry)
408- {
409- auto offset = mPageSize * entry.pushedPages ;
410- uintptr_t pageBusAddress = entry.busAddress + offset;
411- return pageBusAddress;
412- }
413-
414374void CrorcDmaChannel::pushFreeFifoPage (int readyFifoIndex, uintptr_t pageBusAddress)
415375{
416376 size_t pageWords = mPageSize / 4 ; // Size in 32-bit words
0 commit comments