6#include "dawn/prog/buffer.hxx"
11#include "dawn/debug.hxx"
12#include "dawn/io/common.hxx"
13#include "dawn/io/ddata.hxx"
14#include "dawn/io/virt.hxx"
18uint32_t CProgBuffer::resolveRingIndex(
const SBufferBind *bind, uint32_t sel, uint32_t depth)
20 DAWNASSERT(bind !=
nullptr,
"nullptr bind");
21 DAWNASSERT(bind->count > 0,
"count must be > 0");
22 DAWNASSERT(depth > 0,
"depth must be > 0");
24 return (bind->head + depth - 1u - sel) % depth;
27int CProgBuffer::srcNotifyCb(
void *priv,
io_ddata_t *data)
30 if (self ==
nullptr || !self->bind->captureActive)
35 return self->captureBind(data);
38void CProgBuffer::selSetCb(
CIOVirt *io,
void *priv)
46 SBufferBind *bind = self->bind;
47 int ret = io->getVal(bind->selData->getDataPtr(), bind->selData->getDataSize());
50 DAWNERR(
"buffer: failed to read selector value: %d\n", ret);
54 bind->selectedOffset = bind->selData->get<uint32_t>(0);
55 ret = self->updateSelected();
58 DAWNERR(
"buffer: selector apply failed: %d\n", ret);
62void CProgBuffer::statGetCb(
CIOVirt *io,
void *priv)
71 int ret = self->updateStat();
74 DAWNERR(
"buffer: stat update failed: %d\n", ret);
83 bind =
new (std::nothrow) SBufferBind();
98 bind->outData =
nullptr;
99 bind->selData =
nullptr;
100 bind->statData =
nullptr;
104 bind->selectedOffset = 0;
105 bind->snapshotSeq = 0;
106 bind->captureActive =
false;
116int CProgBuffer::configureDesc(
const CDescObject &desc)
121 for (
size_t i = 0; i < desc.
getSize(); i++)
127 DAWNERR(
"buffer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
135 const size_t wpe =
sizeof(SProgBufferIOBind) / 4;
140 DAWNERR(
"buffer: invalid IOBIND size %d\n", item->
cfgid.
s.
size);
146 DAWNERR(
"buffer: only one IOBIND per instance is supported\n");
150 const SProgBufferIOBind *cfg =
151 reinterpret_cast<const SProgBufferIOBind *
>(item->
data);
153 ret = allocBind(cfg->src.v, cfg->out.v, cfg->sel.v, cfg->stat.v);
168 DAWNERR(
"buffer: invalid DEPTH size %d\n", item->
cfgid.
s.
size);
183 DAWNERR(
"buffer: invalid FLAGS size %d\n", item->
cfgid.
s.
size);
198 DAWNERR(
"buffer: invalid CHUNK_SIZE size %d\n", item->
cfgid.
s.
size);
209 DAWNERR(
"buffer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
218int CProgBuffer::updateStat()
220 uint32_t runtimeFlags = 0;
221 bool full = (bind->count == depth);
222 bool rangeError = (bind->count > 0 && bind->selectedOffset >= bind->count);
226 runtimeFlags |= RUNTIME_RUNNING;
229 if (bind->captureActive)
231 runtimeFlags |= RUNTIME_CAPTURE_ACTIVE;
236 runtimeFlags |= RUNTIME_FULL;
241 runtimeFlags |= RUNTIME_ERROR_RANGE;
244 bind->statData->get<uint32_t>(STAT_COUNT) = bind->count;
245 bind->statData->get<uint32_t>(STAT_DEPTH) = depth;
246 bind->statData->get<uint32_t>(STAT_HEAD) = bind->head;
247 bind->statData->get<uint32_t>(STAT_OVERFLOW) = bind->overflow;
248 bind->statData->get<uint32_t>(STAT_SNAPSHOT_SEQ) = bind->snapshotSeq;
249 bind->statData->get<uint32_t>(STAT_RUNTIME_FLAGS) = runtimeFlags;
250 bind->statData->get<uint32_t>(STAT_SELECTED_OFFSET) = bind->selectedOffset;
251 bind->statData->get<uint32_t>(STAT_RESERVED) = 0;
253 return bind->stat->setVal(bind->statData->getDataPtr(), bind->statData->getDataSize());
256int CProgBuffer::updateSelected()
259 size_t sampleSize = bind->src->getDataSize();
260 uint8_t *out =
static_cast<uint8_t *
>(bind->outData->getDataPtr());
262 std::memset(bind->outData->getDataPtr(), 0, bind->outData->getDataSize());
264 if (bind->count == 0)
267 ret = bind->out->setVal(bind->outData->getDataPtr(), bind->outData->getDataSize());
276 if (bind->selectedOffset >= bind->count)
282 for (uint32_t i = 0; i < chunkSize; i++)
284 uint32_t sel = bind->selectedOffset + i;
285 if (sel >= bind->count)
290 uint32_t idx = resolveRingIndex(bind, sel, depth);
291 std::memcpy(out + (i * sampleSize), bind->ring->getDataPtr(idx), sampleSize);
296 ret = bind->out->setVal(bind->outData->getDataPtr(), bind->outData->getDataSize());
307 if (!bind->captureActive)
312 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
314 bind->captureActive =
false;
319 bind->ring->getTs(bind->head) = data->
getTs(0);
321 bind->head = (bind->head + 1u) % depth;
322 if (bind->count < depth)
331 return updateSelected();
334void CProgBuffer::clearBind()
339 bind->selectedOffset = 0;
340 bind->snapshotSeq = 0;
342 std::memset(bind->outData->getDataPtr(), 0, bind->outData->getDataSize());
345int CProgBuffer::validateBind()
347 bind->src =
getIO(bind->srcId);
348 if (bind->src ==
nullptr)
350 DAWNERR(
"buffer: src 0x%" PRIx32
" not found\n", bind->srcId);
354 bind->out =
reinterpret_cast<CIOVirt *
>(
getIO(bind->outId));
355 if (bind->out ==
nullptr)
357 DAWNERR(
"buffer: out 0x%" PRIx32
" not found\n", bind->outId);
361 bind->sel =
reinterpret_cast<CIOVirt *
>(
getIO(bind->selId));
362 if (bind->sel ==
nullptr)
364 DAWNERR(
"buffer: sel 0x%" PRIx32
" not found\n", bind->selId);
368 bind->stat =
reinterpret_cast<CIOVirt *
>(
getIO(bind->statId));
369 if (bind->stat ==
nullptr)
371 DAWNERR(
"buffer: stat 0x%" PRIx32
" not found\n", bind->statId);
375 if (!bind->src->isNotify())
377 DAWNERR(
"buffer: src 0x%" PRIx32
" has no notify support\n", bind->src->getIdV());
381 if (bind->out->getDtype() != bind->src->getDtype())
383 DAWNERR(
"buffer: out IO incompatible with src 0x%" PRIx32
"\n", bind->src->getIdV());
389 DAWNERR(
"buffer: sel IO must use uint32 dtype\n");
395 DAWNERR(
"buffer: stat IO must use uint32 dtype\n");
402int CProgBuffer::allocateBind()
405 const size_t srcDim = bind->src->getDataDim();
410 DAWNERR(
"buffer: src dimension must be > 0\n");
414 outDim = srcDim * chunkSize;
422 ret = bind->out->initialize(outDim, 1,
true);
425 DAWNERR(
"buffer: out initialize failed: %d\n", ret);
430 ret = prepareWritableTarget(bind->sel, 1,
false);
433 DAWNERR(
"buffer: sel initialize failed: %d\n", ret);
437 ret = prepareWritableTarget(bind->stat, STAT_WORDS,
false);
440 DAWNERR(
"buffer: stat initialize failed: %d\n", ret);
445 bind->src->getDtypeSize(), srcDim, depth, bind->src->getDtype(), bind->src->isTimestamp());
446 if (bind->ring ==
nullptr || !bind->ring->isAllocated())
449 bind->ring =
nullptr;
453 bind->outData = bind->out->ddata_alloc(1);
454 bind->selData = bind->sel->ddata_alloc(1);
455 bind->statData = bind->stat->ddata_alloc(1);
457 if (bind->outData ==
nullptr || bind->selData ==
nullptr || bind->statData ==
nullptr)
465CProgBuffer::~CProgBuffer()
472 int ret = configureDesc(
getDesc());
475 DAWNERR(
"buffer: configure failed: %d\n", ret);
481 DAWNERR(
"buffer: no binding configured\n");
487 DAWNERR(
"buffer: depth must be > 0\n");
493 DAWNERR(
"buffer: chunk_size must be > 0\n");
497 if (chunkSize > depth)
499 DAWNERR(
"buffer: chunk_size must be <= depth\n");
503 uint32_t validFlags = FLAG_AUTO_START | FLAG_MODE_ONESHOT | FLAG_KEEP_DATA_ON_STOP;
504 if ((flags & ~validFlags) != 0)
506 DAWNERR(
"buffer: unsupported FLAGS bits 0x%" PRIx32
"\n", flags & ~validFlags);
517 ret = validateBind();
523 ret = allocateBind();
529 ret = bind->src->setNotifier(srcNotifyCb, 0,
this);
532 DAWNERR(
"buffer: set notifier failed for 0x%" PRIx32
": %d\n", bind->src->getIdV(), ret);
536 return updateSelected();
546 delete bind->outData;
547 delete bind->selData;
548 delete bind->statData;
558 bind->captureActive = (flags & FLAG_AUTO_START) != 0;
560 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
562 bind->captureActive =
false;
570 bind->sel->setCallbackSet(selSetCb,
this);
571 bind->stat->setCallbackGet(statGetCb,
this);
579 bool keep = (flags & FLAG_KEEP_DATA_ON_STOP) != 0;
586 bind->captureActive =
false;
588 if (bind->sel !=
nullptr)
590 bind->sel->setCallbackSet(
nullptr,
nullptr);
593 if (bind->stat !=
nullptr)
595 bind->stat->setCallbackGet(
nullptr,
nullptr);
598 if (!keep && bind->ring !=
nullptr && bind->outData !=
nullptr)
603 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
616void CProgBuffer::cmdReset()
618 if (bind->ring !=
nullptr && bind->outData !=
nullptr)
623 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
629void CProgBuffer::cmdStartCapture()
631 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
633 bind->captureActive =
false;
637 bind->captureActive =
true;
640 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
646void CProgBuffer::cmdStopCapture()
648 bind->captureActive =
false;
649 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
@ IO_CLASS_VIRT
Virtual I/O.
Virtual I/O type for user-provided data and callbacks.
@ STATE_RUNNING
Object is running.
virtual EObjectState getState() const
Get current operational state.
CDescObject & getDesc()
Get descriptor object for this object.
@ CMD_RESET
Reset object internal state.
@ CMD_TRIGGER2
Object-specific trigger slot 2.
@ CMD_TRIGGER1
Object-specific trigger slot 1.
Notify-driven history buffer Program.
int doStart()
Start implementation hook.
int deinit()
De-initialize object.
int init()
One-time initialize object after bindings are resolved.
int trigger(uint8_t cmd)
Execute a trigger command.
@ PROG_BUFFER_CFG_IOBIND
I/O binding configuration.
@ PROG_BUFFER_CFG_CHUNK_SIZE
Output samples per read.
@ PROG_BUFFER_CFG_FLAGS
Config flags.
@ PROG_BUFFER_CFG_DEPTH
Buffer depth.
int configure()
Configure object from descriptor data.
int doStop()
Stop implementation hook.
bool hasThread() const
Check if a background thread is active.
@ PROG_CLASS_BUFFER
Notify-driven history capture buffer.
uint32_t ObjectCfgData_t
Configuration data element - single 32-bit word.
static uint32_t cfgToU32(ObjectCfgData_t x)
Convert ObjectCfgData_t to uint32_t.
Out-of-tree user-extension hooks for Dawn.
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Heap-allocated dynamic I/O data buffer.
size_t getDataSize()
Get data size in bytes.
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
io_ts_t & getTs(size_t batch=0)
Get timestamp reference for batch.
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.