Dawn Framework 1.0
Universal data acquisition framework for embedded systems
manytoone.cxx
1// dawn/src/prog/manytoone.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/manytoone.hxx"
7
8#include <new>
9
10#include "dawn/debug.hxx"
11#include "dawn/io/common.hxx"
12
13using namespace dawn;
14
15CProgManyToOne::CProgManyToOne(CDescObject &desc)
16 : CProgCommon(desc)
17 , output(nullptr)
18 , outputId(0)
19 , dataBuf(nullptr)
20 , active(false)
21 , registered(false)
22{
23}
24
25CProgManyToOne::~CProgManyToOne()
26{
27 deinit();
28}
29
30int CProgManyToOne::allocInput(SObjectId::ObjectId ioId)
31{
32 SInput input;
33
34 input.owner = this;
35 input.io = nullptr;
36 input.ioId = ioId;
37 inputs.push_back(input);
38 setObjectMapItem(ioId, nullptr);
39 return OK;
40}
41
42int CProgManyToOne::configureDesc(const CDescObject &desc)
43{
45 const SObjectId::UObjectId *ids;
46 size_t offset = 0;
47
48 for (size_t i = 0; i < desc.getSize(); i++)
49 {
50 item = desc.objectCfgItemNext(offset);
51
52 if (item->cfgid.s.cls != CProgCommon::PROG_CLASS_MANYTOONE)
53 {
54 DAWNERR("manytoone: unsupported cfg class 0x%" PRIx32 "\n", item->cfgid.v);
55 return -EINVAL;
56 }
57
58 switch (item->cfgid.s.id)
59 {
60 case PROG_MANYTOONE_CFG_INPUTS:
61 {
62 if (item->cfgid.s.size == 0)
63 {
64 DAWNERR("manytoone: INPUTS must not be empty\n");
65 return -EINVAL;
66 }
67
68 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
69 for (size_t j = 0; j < item->cfgid.s.size; j++)
70 {
71 int ret = allocInput(ids[j].v);
72 if (ret != OK)
73 {
74 return ret;
75 }
76 }
77 break;
78 }
79
80 case PROG_MANYTOONE_CFG_OUTPUT:
81 {
82 if (item->cfgid.s.size != 1)
83 {
84 DAWNERR("manytoone: OUTPUT must have one item\n");
85 return -EINVAL;
86 }
87
88 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
89 outputId = ids[0].v;
90 setObjectMapItem(outputId, nullptr);
91 break;
92 }
93
94 default:
95 DAWNERR("manytoone: unsupported cfg id %u\n", item->cfgid.s.id);
96 return -EINVAL;
97 }
98 }
99
100 if (inputs.empty() || outputId == 0)
101 {
102 DAWNERR("manytoone: inputs and output are required\n");
103 return -EINVAL;
104 }
105
106 return OK;
107}
108
110{
111 return configureDesc(getDesc());
112}
113
114int CProgManyToOne::validateShape(CIOCommon *io) const
115{
116 if (io == nullptr || output == nullptr)
117 {
118 return -EIO;
119 }
120
121 if (!io->isRead() || !io->isNotify() || io->getDtype() != output->getDtype() ||
122 io->getDataDim() != output->getDataDim() || io->isTimestamp() != output->isTimestamp() ||
123 io->getDataSize() != output->getDataSize())
124 {
125 return -EINVAL;
126 }
127
128 return OK;
129}
130
132{
133 output = getIO(outputId);
134 if (output == nullptr)
135 {
136 DAWNERR("manytoone: output IO 0x%" PRIx32 " not found\n", outputId);
137 return -EIO;
138 }
139
140 for (auto &input : inputs)
141 {
142 input.io = getIO(input.ioId);
143 if (input.io == nullptr)
144 {
145 DAWNERR("manytoone: input IO 0x%" PRIx32 " not found\n", input.ioId);
146 return -EIO;
147 }
148 }
149
150 int ret = prepareWritableTarget(output, inputs[0].io->getDataDim(), true);
151 if (ret != OK)
152 {
153 DAWNERR("manytoone: output prepare failed %d\n", ret);
154 return ret;
155 }
156
157 for (auto &input : inputs)
158 {
159 ret = validateShape(input.io);
160 if (ret != OK)
161 {
162 DAWNERR("manytoone: input 0x%" PRIx32 " incompatible\n", input.ioId);
163 return ret;
164 }
165 }
166
167 dataBuf = output->ddata_alloc(1);
168 if (dataBuf == nullptr)
169 {
170 DAWNERR("manytoone: data allocation failed\n");
171 return -ENOMEM;
172 }
173
174 return OK;
175}
176
178{
179 doStop();
180 delete dataBuf;
181 dataBuf = nullptr;
182 output = nullptr;
183 outputId = 0;
184 inputs.clear();
185 return OK;
186}
187
188int CProgManyToOne::ioNotifierCb(void *priv, io_ddata_t *data)
189{
190 SInput *input = static_cast<SInput *>(priv);
191
192 if (input == nullptr || input->owner == nullptr || !input->owner->active || data == nullptr)
193 {
194 return OK;
195 }
196
197 int ret = input->owner->output->setData(*data);
198 if (ret != OK)
199 {
200 DAWNERR("manytoone: output setData failed %d\n", ret);
201 return ret;
202 }
203
204 return OK;
205}
206
208{
209 if (!registered)
210 {
211 for (auto &input : inputs)
212 {
213 int ret = input.io->setNotifier(ioNotifierCb, 0, &input);
214 if (ret != OK)
215 {
216 DAWNERR("manytoone: setNotifier failed for 0x%" PRIx32 ": %d\n", input.ioId, ret);
217 return ret;
218 }
219 }
220 registered = true;
221 }
222
223 active = true;
224 writeInput(0);
225 return OK;
226}
227
229{
230 if (registered)
231 {
232 for (auto &input : inputs)
233 {
234 if (input.io != nullptr)
235 {
236 input.io->setNotifier(nullptr, 0, nullptr);
237 }
238 }
239 registered = false;
240 }
241
242 active = false;
243 return OK;
244}
245
247{
248 return false;
249}
250
251void CProgManyToOne::writeInput(size_t index)
252{
253 if (index >= inputs.size() || dataBuf == nullptr || output == nullptr)
254 {
255 return;
256 }
257
258 if (inputs[index].io->getData(*dataBuf, 1) != OK)
259 {
260 return;
261 }
262
263 int ret = output->setData(*dataBuf);
264 if (ret != OK)
265 {
266 DAWNERR("manytoone: output setData failed %d\n", ret);
267 }
268}
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
int getData(IODataCmn &data, size_t len, size_t offset=0)
Get data from I/O (public interface with stats tracking).
Definition common.hxx:353
virtual bool isNotify() const =0
Check if IO supports notifications.
bool isTimestamp() const
Check if I/O supports timestamp.
Definition common.cxx:189
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
virtual size_t getDataSize() const =0
Get data size in bytes.
virtual bool isRead() const =0
Check if IO supports read operations.
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
bool hasThread() const
Check if a background thread is active.
int doStart()
Start implementation hook.
int init()
One-time initialize object after bindings are resolved.
int deinit()
De-initialize object.
int doStop()
Stop implementation hook.
int configure()
Configure object from descriptor data.
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
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