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::outGetCb(
CIOVirt *io,
void *priv)
47 int ret = self->updateSelected();
50 DAWNERR(
"buffer: out get update failed: %d\n", ret);
54void CProgBuffer::selSetCb(
CIOVirt *io,
void *priv)
62 SBufferBind *bind = self->bind;
63 int ret = io->getVal(bind->selData->getDataPtr(), bind->selData->getDataSize());
66 DAWNERR(
"buffer: failed to read selector value: %d\n", ret);
70 bind->selectedOffset = bind->selData->get<uint32_t>(0);
71 ret = self->updateSelected();
74 DAWNERR(
"buffer: selector apply failed: %d\n", ret);
78void CProgBuffer::statGetCb(
CIOVirt *io,
void *priv)
87 int ret = self->updateStat();
90 DAWNERR(
"buffer: stat update failed: %d\n", ret);
99 bind =
new (std::nothrow) SBufferBind();
112 bind->stat =
nullptr;
113 bind->ring =
nullptr;
114 bind->outData =
nullptr;
115 bind->selData =
nullptr;
116 bind->statData =
nullptr;
120 bind->selectedOffset = 0;
121 bind->snapshotSeq = 0;
122 bind->captureActive =
false;
132int CProgBuffer::configureDesc(
const CDescObject &desc)
137 for (
size_t i = 0; i < desc.
getSize(); i++)
143 DAWNERR(
"buffer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
151 const size_t wpe =
sizeof(SProgBufferIOBind) / 4;
156 DAWNERR(
"buffer: invalid IOBIND size %d\n", item->
cfgid.
s.
size);
162 DAWNERR(
"buffer: only one IOBIND per instance is supported\n");
166 const SProgBufferIOBind *cfg =
167 reinterpret_cast<const SProgBufferIOBind *
>(item->
data);
169 ret = allocBind(cfg->src.v, cfg->out.v, cfg->sel.v, cfg->stat.v);
184 DAWNERR(
"buffer: invalid DEPTH size %d\n", item->
cfgid.
s.
size);
199 DAWNERR(
"buffer: invalid FLAGS size %d\n", item->
cfgid.
s.
size);
214 DAWNERR(
"buffer: invalid CHUNK_SIZE size %d\n", item->
cfgid.
s.
size);
225 DAWNERR(
"buffer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
234int CProgBuffer::updateStat()
236 uint32_t runtimeFlags = 0;
237 bool full = (bind->count == depth);
238 bool rangeError = (bind->count > 0 && bind->selectedOffset >= bind->count);
242 runtimeFlags |= RUNTIME_RUNNING;
245 if (bind->captureActive)
247 runtimeFlags |= RUNTIME_CAPTURE_ACTIVE;
252 runtimeFlags |= RUNTIME_FULL;
257 runtimeFlags |= RUNTIME_ERROR_RANGE;
260 bind->statData->get<uint32_t>(STAT_COUNT) = bind->count;
261 bind->statData->get<uint32_t>(STAT_DEPTH) = depth;
262 bind->statData->get<uint32_t>(STAT_HEAD) = bind->head;
263 bind->statData->get<uint32_t>(STAT_OVERFLOW) = bind->overflow;
264 bind->statData->get<uint32_t>(STAT_SNAPSHOT_SEQ) = bind->snapshotSeq;
265 bind->statData->get<uint32_t>(STAT_RUNTIME_FLAGS) = runtimeFlags;
266 bind->statData->get<uint32_t>(STAT_SELECTED_OFFSET) = bind->selectedOffset;
267 bind->statData->get<uint32_t>(STAT_RESERVED) = 0;
269 return bind->stat->setVal(bind->statData->getDataPtr(), bind->statData->getDataSize());
272int CProgBuffer::updateSelected()
275 size_t sampleSize = bind->src->getDataSize();
276 uint8_t *out =
static_cast<uint8_t *
>(bind->outData->getDataPtr());
278 std::memset(bind->outData->getDataPtr(), 0, bind->outData->getDataSize());
280 if (bind->count == 0)
283 ret = bind->out->setVal(bind->outData->getDataPtr(), bind->outData->getDataSize());
292 if (bind->selectedOffset >= bind->count)
298 for (uint32_t i = 0; i < chunkSize; i++)
300 uint32_t sel = bind->selectedOffset + i;
301 if (sel >= bind->count)
306 uint32_t idx = resolveRingIndex(bind, sel, depth);
307 std::memcpy(out + (i * sampleSize), bind->ring->getDataPtr(idx), sampleSize);
312 ret = bind->out->setVal(bind->outData->getDataPtr(), bind->outData->getDataSize());
323 if (!bind->captureActive)
328 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
330 bind->captureActive =
false;
335 bind->ring->getTs(bind->head) = data->
getTs(0);
337 bind->head = (bind->head + 1u) % depth;
338 if (bind->count < depth)
347 return updateSelected();
350void CProgBuffer::clearBind()
355 bind->selectedOffset = 0;
356 bind->snapshotSeq = 0;
358 std::memset(bind->outData->getDataPtr(), 0, bind->outData->getDataSize());
361int CProgBuffer::validateBind()
363 bind->src =
getIO(bind->srcId);
364 if (bind->src ==
nullptr)
366 DAWNERR(
"buffer: src 0x%" PRIx32
" not found\n", bind->srcId);
370 bind->out =
reinterpret_cast<CIOVirt *
>(
getIO(bind->outId));
371 if (bind->out ==
nullptr)
373 DAWNERR(
"buffer: out 0x%" PRIx32
" not found\n", bind->outId);
377 bind->sel =
reinterpret_cast<CIOVirt *
>(
getIO(bind->selId));
378 if (bind->sel ==
nullptr)
380 DAWNERR(
"buffer: sel 0x%" PRIx32
" not found\n", bind->selId);
384 bind->stat =
reinterpret_cast<CIOVirt *
>(
getIO(bind->statId));
385 if (bind->stat ==
nullptr)
387 DAWNERR(
"buffer: stat 0x%" PRIx32
" not found\n", bind->statId);
391 if (!bind->src->isNotify())
393 DAWNERR(
"buffer: src 0x%" PRIx32
" has no notify support\n", bind->src->getIdV());
397 if (bind->out->getDtype() != bind->src->getDtype())
399 DAWNERR(
"buffer: out IO incompatible with src 0x%" PRIx32
"\n", bind->src->getIdV());
405 DAWNERR(
"buffer: sel IO must use uint32 dtype\n");
411 DAWNERR(
"buffer: stat IO must use uint32 dtype\n");
418int CProgBuffer::allocateBind()
421 const size_t srcDim = bind->src->getDataDim();
426 DAWNERR(
"buffer: src dimension must be > 0\n");
430 outDim = srcDim * chunkSize;
438 ret = bind->out->initialize(outDim, 1,
true);
441 DAWNERR(
"buffer: out initialize failed: %d\n", ret);
446 ret = prepareWritableTarget(bind->sel, 1,
false);
449 DAWNERR(
"buffer: sel initialize failed: %d\n", ret);
453 ret = prepareWritableTarget(bind->stat, STAT_WORDS,
false);
456 DAWNERR(
"buffer: stat initialize failed: %d\n", ret);
461 bind->src->getDtypeSize(), srcDim, depth, bind->src->getDtype(), bind->src->isTimestamp());
462 if (bind->ring ==
nullptr || !bind->ring->isAllocated())
465 bind->ring =
nullptr;
469 bind->outData = bind->out->ddata_alloc(1);
470 bind->selData = bind->sel->ddata_alloc(1);
471 bind->statData = bind->stat->ddata_alloc(1);
473 if (bind->outData ==
nullptr || bind->selData ==
nullptr || bind->statData ==
nullptr)
481CProgBuffer::~CProgBuffer()
488 int ret = configureDesc(
getDesc());
491 DAWNERR(
"buffer: configure failed: %d\n", ret);
497 DAWNERR(
"buffer: no binding configured\n");
503 DAWNERR(
"buffer: depth must be > 0\n");
509 DAWNERR(
"buffer: chunk_size must be > 0\n");
513 if (chunkSize > depth)
515 DAWNERR(
"buffer: chunk_size must be <= depth\n");
519 uint32_t validFlags = FLAG_AUTO_START | FLAG_MODE_ONESHOT | FLAG_KEEP_DATA_ON_STOP;
520 if ((flags & ~validFlags) != 0)
522 DAWNERR(
"buffer: unsupported FLAGS bits 0x%" PRIx32
"\n", flags & ~validFlags);
533 ret = validateBind();
539 ret = allocateBind();
545 ret = bind->src->setNotifier(srcNotifyCb, 0,
this);
548 DAWNERR(
"buffer: set notifier failed for 0x%" PRIx32
": %d\n", bind->src->getIdV(), ret);
552 return updateSelected();
562 delete bind->outData;
563 delete bind->selData;
564 delete bind->statData;
574 bind->captureActive = (flags & FLAG_AUTO_START) != 0;
576 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
578 bind->captureActive =
false;
581 bind->out->setCallbackGet(outGetCb,
this);
582 bind->sel->setCallbackSet(selSetCb,
this);
583 bind->stat->setCallbackGet(statGetCb,
this);
591 bool keep = (flags & FLAG_KEEP_DATA_ON_STOP) != 0;
598 bind->captureActive =
false;
600 if (bind->out !=
nullptr)
602 bind->out->setCallbackGet(
nullptr,
nullptr);
605 if (bind->sel !=
nullptr)
607 bind->sel->setCallbackSet(
nullptr,
nullptr);
610 if (bind->stat !=
nullptr)
612 bind->stat->setCallbackGet(
nullptr,
nullptr);
615 if (!keep && bind->ring !=
nullptr && bind->outData !=
nullptr)
620 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
633void CProgBuffer::cmdReset()
635 if (bind->ring !=
nullptr && bind->outData !=
nullptr)
640 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
646void CProgBuffer::cmdStartCapture()
648 if ((flags & FLAG_MODE_ONESHOT) && bind->count >= depth)
650 bind->captureActive =
false;
654 bind->captureActive =
true;
657 if (bind->stat !=
nullptr && bind->statData !=
nullptr)
663void CProgBuffer::cmdStopCapture()
665 bind->captureActive =
false;
666 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.