Skip to content

Commit fadaf1a

Browse files
PascalBoeschotenkostorr
authored andcommitted
Modifications for superpage-aware C-RORC firmware
1 parent d09cdb0 commit fadaf1a

File tree

2 files changed

+79
-123
lines changed

2 files changed

+79
-123
lines changed

src/Crorc/CrorcDmaChannel.cxx

Lines changed: 60 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,26 @@ CrorcDmaChannel::~CrorcDmaChannel()
9393

9494
void 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

184178
void CrorcDmaChannel::deviceStopDma()
@@ -283,109 +277,92 @@ void CrorcDmaChannel::startDataReceiving()
283277

284278
int CrorcDmaChannel::getTransferQueueAvailable()
285279
{
286-
return mSuperpageQueue.getQueueAvailable();
280+
return TRANSFER_QUEUE_CAPACITY - mTransferQueue.size();
287281
}
288282

289283
int CrorcDmaChannel::getReadyQueueSize()
290284
{
291-
return mSuperpageQueue.getFilled().size();
285+
return mReadyQueue.size();
292286
}
293287

294288
auto 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

299296
void 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

320327
auto 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

325337
void 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-
414374
void CrorcDmaChannel::pushFreeFifoPage(int readyFifoIndex, uintptr_t pageBusAddress)
415375
{
416376
size_t pageWords = mPageSize / 4; // Size in 32-bit words

src/Crorc/CrorcDmaChannel.h

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#include <mutex>
1111
#include <unordered_map>
12-
#include <boost/circular_buffer_fwd.hpp>
12+
#include <boost/circular_buffer.hpp>
1313
#include <boost/scoped_ptr.hpp>
1414
#include "DmaChannelPdaBase.h"
1515
#include "Crorc.h"
@@ -57,14 +57,18 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
5757
virtual void deviceResetChannel(ResetLevel::type resetLevel) override;
5858

5959
private:
60-
/// Limits the number of superpages allowed in the queue
61-
static constexpr size_t MAX_SUPERPAGES = 32;
62-
6360
/// Firmware FIFO Size
64-
static constexpr size_t FIFO_QUEUE_MAX = READYFIFO_ENTRIES;
61+
static constexpr size_t TRANSFER_QUEUE_CAPACITY = READYFIFO_ENTRIES;
62+
63+
/// Max amount of superpages in the ready queue (i.e. finished transfer).
64+
/// This is an arbitrary size, can easily be increased if more headroom is needed.
65+
static constexpr size_t READY_QUEUE_CAPACITY = READYFIFO_ENTRIES;
6566

66-
using SuperpageQueueType = SuperpageQueue<MAX_SUPERPAGES>;
67-
using SuperpageQueueEntry = SuperpageQueueType::SuperpageQueueEntry;
67+
/// Minimum number of superpages needed to bootstrap DMA
68+
static constexpr size_t DMA_START_REQUIRED_SUPERPAGES = 1;
69+
//static constexpr size_t DMA_START_REQUIRED_SUPERPAGES = READYFIFO_ENTRIES;
70+
71+
using SuperpageQueue = boost::circular_buffer<Superpage>;
6872

6973
/// Namespace for enum describing the status of a page's arrival
7074
struct DataArrivalStatus
@@ -77,8 +81,6 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
7781
};
7882
};
7983

80-
uintptr_t getNextSuperpageBusAddress(const SuperpageQueueEntry& superpage);
81-
8284
/// C-RORC function helper
8385
Crorc::Crorc getCrorc()
8486
{
@@ -90,11 +92,6 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
9092
return reinterpret_cast<ReadyFifo*>(mReadyFifoAddressUser);
9193
}
9294

93-
ReadyFifo* getReadyFifoBus()
94-
{
95-
return reinterpret_cast<ReadyFifo*>(mReadyFifoAddressBus);
96-
}
97-
9895
/// Enables data receiving in the RORC
9996
void startDataReceiving();
10097

@@ -109,12 +106,6 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
109106
/// Check if data has arrived
110107
DataArrivalStatus::type dataArrived(int index);
111108

112-
/// Starts pending DMA with given superpage for the initial pages
113-
void startPendingDma(SuperpageQueueEntry& superpage);
114-
115-
/// Push a page into a superpage
116-
void pushIntoSuperpage(SuperpageQueueEntry& superpage);
117-
118109
/// Get front index of FIFO
119110
int getFifoFront() const
120111
{
@@ -126,6 +117,9 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
126117
return crorcBar.get();
127118
}
128119

120+
/// Starts pending DMA with given superpage for the initial pages
121+
void startPendingDma();
122+
129123
/// BAR used for DMA engine and configuration
130124
std::shared_ptr<CrorcBar> crorcBar;
131125

@@ -147,8 +141,11 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
147141
/// Amount of elements in the firmware FIFO
148142
int mFifoSize = 0;
149143

150-
/// Queue for superpages
151-
SuperpageQueueType mSuperpageQueue;
144+
/// Queue for superpages that are pushed to the firmware FIFO
145+
SuperpageQueue mTransferQueue {TRANSFER_QUEUE_CAPACITY};
146+
147+
/// Queue for superpages that are filled
148+
SuperpageQueue mReadyQueue {READY_QUEUE_CAPACITY};
152149

153150
/// Address of DMA buffer in userspace
154151
uintptr_t mDmaBufferUserspace = 0;
@@ -157,7 +154,6 @@ class CrorcDmaChannel final : public DmaChannelPdaBase
157154
/// superpage to actually start.
158155
bool mPendingDmaStart = false;
159156

160-
161157
// These variables are configuration parameters
162158

163159
/// DMA page size

0 commit comments

Comments
 (0)