Dawn Framework 1.0
Universal data acquisition framework for embedded systems
vecpack.cxx
1// dawn/src/prog/vecpack.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/vecpack.hxx"
7
8#include <cstring>
9#include <new>
10
11#include "dawn/debug.hxx"
12#include "dawn/io/common.hxx"
13#include "dawn/io/virt.hxx"
14
15using namespace dawn;
16
17CProgVecPack::CProgVecPack(CDescObject &desc)
18 : CProgCommon(desc)
19 , output(nullptr)
20 , outputId(0)
21 , outputData(nullptr)
22 , lastOutputData(nullptr)
23 , active(false)
24 , registered(false)
25{
26}
27
28CProgVecPack::~CProgVecPack()
29{
30 deinit();
31}
32
33int CProgVecPack::allocInput(SObjectId::ObjectId ioId)
34{
35 SVecInput input;
36
37 input.owner = this;
38 input.io = nullptr;
39 input.ioId = ioId;
40 input.data = nullptr;
41 input.offset = 0;
42 input.usesSetCallback = false;
43 inputs.push_back(input);
44 setObjectMapItem(ioId, nullptr);
45 return OK;
46}
47
48int CProgVecPack::configureDesc(const CDescObject &desc)
49{
51 const SObjectId::UObjectId *ids;
52 size_t offset = 0;
53
54 for (size_t i = 0; i < desc.getSize(); i++)
55 {
56 item = desc.objectCfgItemNext(offset);
57
58 if (item->cfgid.s.cls != CProgCommon::PROG_CLASS_VECPACK)
59 {
60 DAWNERR("vecpack: unsupported cfg class 0x%" PRIx32 "\n", item->cfgid.v);
61 return -EINVAL;
62 }
63
64 switch (item->cfgid.s.id)
65 {
66 case PROG_VECPACK_CFG_INPUTS:
67 {
68 if (item->cfgid.s.size == 0)
69 {
70 DAWNERR("vecpack: INPUTS must not be empty\n");
71 return -EINVAL;
72 }
73
74 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
75 for (size_t j = 0; j < item->cfgid.s.size; j++)
76 {
77 int ret = allocInput(ids[j].v);
78 if (ret != OK)
79 {
80 return ret;
81 }
82 }
83
84 break;
85 }
86
87 case PROG_VECPACK_CFG_OUTPUT:
88 {
89 if (item->cfgid.s.size != 1)
90 {
91 DAWNERR("vecpack: OUTPUT must have one item\n");
92 return -EINVAL;
93 }
94
95 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
96 outputId = ids[0].v;
97 setObjectMapItem(outputId, nullptr);
98 break;
99 }
100
101 default:
102 {
103 DAWNERR("vecpack: unsupported cfg id %u\n", item->cfgid.s.id);
104 return -EINVAL;
105 }
106 }
107 }
108
109 if (inputs.empty() || outputId == 0)
110 {
111 DAWNERR("vecpack: inputs and output are required\n");
112 return -EINVAL;
113 }
114
115 return OK;
116}
117
119{
120 return configureDesc(getDesc());
121}
122
124{
125 size_t dim = 0;
126 int ret;
127
128 output = getIO(outputId);
129 if (output == nullptr)
130 {
131 DAWNERR("vecpack: output IO 0x%" PRIx32 " not found\n", outputId);
132 return -EIO;
133 }
134
135 for (size_t i = 0; i < inputs.size(); i++)
136 {
137 inputs[i].io = getIO(inputs[i].ioId);
138 if (inputs[i].io == nullptr)
139 {
140 DAWNERR("vecpack: input IO 0x%" PRIx32 " not found\n", inputs[i].ioId);
141 return -EIO;
142 }
143
144 if (inputs[i].io->getDataDim() == 0)
145 {
146 ret = prepareWritableTarget(inputs[i].io, 1, false);
147 if (ret != OK)
148 {
149 DAWNERR("vecpack: input prepare failed %d\n", ret);
150 return ret;
151 }
152 }
153
154 if (!inputs[i].io->isRead() || inputs[i].io->getDtype() != output->getDtype())
155 {
156 DAWNERR("vecpack: input 0x%" PRIx32 " incompatible with output 0x%" PRIx32 "\n",
157 inputs[i].ioId,
158 outputId);
159 return -EINVAL;
160 }
161
162 inputs[i].offset = dim;
163 dim += inputs[i].io->getDataDim();
164 inputs[i].data = inputs[i].io->ddata_alloc(1);
165 if (inputs[i].data == nullptr)
166 {
167 DAWNERR("vecpack: input data allocation failed\n");
168 return -ENOMEM;
169 }
170 }
171
172 ret = prepareWritableTarget(output, dim, true);
173 if (ret != OK)
174 {
175 DAWNERR("vecpack: output prepare failed %d\n", ret);
176 return ret;
177 }
178
179 if (output->getDataDim() != dim)
180 {
181 DAWNERR(
182 "vecpack: output dimension mismatch expected %zu got %zu\n", dim, output->getDataDim());
183 return -EINVAL;
184 }
185
186 outputData = output->ddata_alloc(1);
187 lastOutputData = output->ddata_alloc(1);
188 if (outputData == nullptr || lastOutputData == nullptr)
189 {
190 DAWNERR("vecpack: output data allocation failed\n");
191 return -ENOMEM;
192 }
193
194 std::memset(lastOutputData->getDataPtr(), 0xff, lastOutputData->getDataSize());
195 return OK;
196}
197
199{
200 doStop();
201
202 for (auto &input : inputs)
203 {
204 delete input.data;
205 input.data = nullptr;
206 }
207
208 inputs.clear();
209 delete outputData;
210 outputData = nullptr;
211 delete lastOutputData;
212 lastOutputData = nullptr;
213 output = nullptr;
214 outputId = 0;
215 return OK;
216}
217
218int CProgVecPack::ioNotifierCb(void *priv, io_ddata_t *data)
219{
220 SVecInput *input = static_cast<SVecInput *>(priv);
221
222 if (input == nullptr || input->owner == nullptr || !input->owner->active)
223 {
224 return OK;
225 }
226
227 if (data != nullptr && input->data != nullptr)
228 {
229 std::memcpy(input->data->getDataPtr(), data->getDataPtr(), input->data->getDataSize());
230 }
231
232 input->owner->updateOutput();
233 return OK;
234}
235
236void CProgVecPack::ioSetCb(CIOVirt *io, void *priv)
237{
238 SVecInput *input = static_cast<SVecInput *>(priv);
239
240 UNUSED(io);
241
242 if (input == nullptr || input->owner == nullptr || !input->owner->active)
243 {
244 return;
245 }
246
247 input->owner->updateOutput();
248}
249
251{
252 int ret;
253
254 if (!registered)
255 {
256 for (auto &input : inputs)
257 {
258 if (input.io->isNotify())
259 {
260 ret = input.io->setNotifier(ioNotifierCb, 0, &input);
261 if (ret != OK)
262 {
263 DAWNERR("vecpack: setNotifier failed for 0x%" PRIx32 ": %d\n", input.ioId, ret);
264 return ret;
265 }
266
267 continue;
268 }
269
270 if (input.io->getCls() != CIOCommon::IO_CLASS_VIRT)
271 {
272 continue;
273 }
274
275 ret = reinterpret_cast<CIOVirt *>(input.io)->setCallbackSet(ioSetCb, &input);
276 if (ret != OK)
277 {
278 DAWNERR("vecpack: setCallbackSet failed for 0x%" PRIx32 ": %d\n", input.ioId, ret);
279 return ret;
280 }
281
282 input.usesSetCallback = true;
283 }
284
285 registered = true;
286 }
287
288 active = true;
289 updateOutput();
290 return OK;
291}
292
294{
295 if (registered)
296 {
297 for (auto &input : inputs)
298 {
299 if (input.io == nullptr)
300 {
301 continue;
302 }
303
304 if (input.io->isNotify())
305 {
306 input.io->setNotifier(nullptr, 0, nullptr);
307 }
308 else if (input.usesSetCallback && input.io->getCls() == CIOCommon::IO_CLASS_VIRT)
309 {
310 reinterpret_cast<CIOVirt *>(input.io)->setCallbackSet(nullptr, nullptr);
311 input.usesSetCallback = false;
312 }
313 }
314
315 registered = false;
316 }
317
318 active = false;
319 return OK;
320}
321
323{
324 return false;
325}
326
327void CProgVecPack::updateOutput()
328{
329 int ret;
330
331 if (outputData == nullptr || lastOutputData == nullptr || output == nullptr)
332 {
333 return;
334 }
335
336 for (auto &input : inputs)
337 {
338 if (input.io->getData(*input.data, 1) != OK)
339 {
340 return;
341 }
342
343 std::memcpy(static_cast<uint8_t *>(outputData->getDataPtr()) +
344 input.offset * input.io->getDtypeSize(),
345 input.data->getDataPtr(),
346 input.data->getDataSize());
347 }
348
349 if (std::memcmp(
350 outputData->getDataPtr(), lastOutputData->getDataPtr(), outputData->getDataSize()) == 0)
351 {
352 return;
353 }
354
355 std::memcpy(lastOutputData->getDataPtr(), outputData->getDataPtr(), outputData->getDataSize());
356 ret = output->setData(*outputData);
357 if (ret != OK)
358 {
359 DAWNERR("vecpack: output setData failed %d\n", ret);
360 }
361}
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
Definition bindable.cxx:41
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Definition bindable.cxx:23
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.
int setData(IODataCmn &data, size_t offset=0)
Set data for I/O (public interface with stats tracking).
Definition common.hxx:392
virtual size_t getDataDim() const =0
Get data vector dimension.
io_ddata_t * ddata_alloc(size_t batch, size_t chunk_size=0)
Allocate data buffer for this I/O.
Definition common.cxx:247
@ IO_CLASS_VIRT
Virtual I/O.
Definition common.hxx:188
Virtual I/O type for user-provided data and callbacks.
Definition virt.hxx:26
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
Base class for all PROG (processing) objects.
Definition common.hxx:27
int doStop()
Stop implementation hook.
Definition vecpack.cxx:293
int deinit()
De-initialize object.
Definition vecpack.cxx:198
bool hasThread() const
Check if a background thread is active.
Definition vecpack.cxx:322
int configure()
Configure object from descriptor data.
Definition vecpack.cxx:118
int doStart()
Start implementation hook.
Definition vecpack.cxx:250
int init()
One-time initialize object after bindings are resolved.
Definition vecpack.cxx:123
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
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).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
size_t getDataSize()
Get data size in bytes.
Definition ddata.hxx:153
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
Definition ddata.hxx:180
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
Definition objectcfg.hxx:94
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.
32-bit encoded object identifier (union with bit field).
Definition objectid.hxx:218
ObjectId v
Raw 32-bit ObjectID value (for comparison, hashing, storage).
Definition objectid.hxx:221