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