onnx2versal
Loading...
Searching...
No Matches
qlinearconv.h
1#ifndef QLINEARCONV_H_
2#define QLINEARCONV_H_
3
4#include <adf.h>
5#include <assert.h>
6
7
42template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
44
45 private:
46 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
47 static constexpr int C_PER_M = C / GROUP;
48
49 alignas(32) TTPARAM (&weights)[M*C_PER_M*KH*KW];
50 alignas(32) int32_t (&bias)[M];
51 float x_scale;
52 float w_scale;
53 float y_scale;
54 TT x_zero;
55 TTPARAM w_zero;
56 TT y_zero;
57
58 float scale;
59
60 public:
62 TTPARAM (&w)[M*C*KH*KW],
63 int32_t (&b)[M],
64 float x_scale,
65 float w_scale,
66 float y_scale,
67 TT x_zero,
68 TTPARAM w_zero,
69 TT y_zero
70 ): weights(w), bias(b), x_scale(x_scale), w_scale(w_scale), y_scale(y_scale), x_zero(x_zero), w_zero(w_zero), y_zero(y_zero) {
71 scale = x_scale*w_scale/y_scale;
72 };
73
74 void filter(
75 input_window<TT>* in,
76 output_window<TT>* out
77 );
78
79 static void registerKernelClass() {
80 static_assert((std::is_same<TT, int8_t>::value));
81 REGISTER_FUNCTION(QLinearConvScalar::filter);
82 REGISTER_PARAMETER(weights);
83 REGISTER_PARAMETER(bias);
84 }
85};
86
87
95template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
97
98 private:
99 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
100
101 alignas(32) TTPARAM (&weights)[M*C*KH*16];
102 alignas(32) int32_t (&bias)[M];
103 float x_scale;
104 float w_scale;
105 float y_scale;
106 TT x_zero;
107 TTPARAM w_zero;
108 TT y_zero;
109
110 // precomputation
111 int scalebits;
112 int16_t scale;
113
114 public:
116 TTPARAM (&w)[M*C*KH*16],
117 int32_t (&b)[M],
118 float x_scale,
119 float w_scale,
120 float y_scale,
121 TT x_zero,
122 TTPARAM w_zero,
123 TT y_zero
124 );
125
126 void filter(
127 input_window<TT>* in,
128 output_window<TT>* out
129 );
130
131 static void registerKernelClass() {
132 static_assert((std::is_same<TT, int8_t>::value));
133 static_assert(KH==5);
134 static_assert(KW==5);
135 static_assert(GROUP == 1);
136 static_assert(INP_W%16==0);
137 static_assert(OUT_W_PAD%16==0);
138 REGISTER_FUNCTION(QLinearConv5x5::filter);
139 REGISTER_PARAMETER(weights);
140 REGISTER_PARAMETER(bias);
141 }
142};
143
144
152template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
154
155 private:
156 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
157
158 alignas(32) TTPARAM (&weights)[M*C*KH*16];
159 alignas(32) int32_t (&bias)[M];
160 float x_scale;
161 float w_scale;
162 float y_scale;
163 TT x_zero;
164 TTPARAM w_zero;
165 TT y_zero;
166
167 // precomputation
168 int scalebits;
169 int32_t scale;
170
171 public:
173 TTPARAM (&w)[M*C*KH*16],
174 int32_t (&b)[M],
175 float x_scale,
176 float w_scale,
177 float y_scale,
178 TT x_zero,
179 TTPARAM w_zero,
180 TT y_zero
181 );
182
183 void filter(
184 input_window<TT>* in,
185 output_window<TT>* out
186 );
187
188 static void registerKernelClass() {
189 static_assert((std::is_same<TT, int8_t>::value));
190 static_assert(GROUP == 1);
191 static_assert(INP_W%16==0);
192 static_assert(OUT_W_PAD%16==0);
193 REGISTER_FUNCTION(QLinearConv5x5Scale32bit::filter);
194 REGISTER_PARAMETER(weights);
195 REGISTER_PARAMETER(bias);
196 }
197};
198
206template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
208
209 private:
210 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
211
212 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : 0x76543210;
213 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
214
215 alignas(32) TTPARAM (&weights)[M*C*16];
216 alignas(32) int32_t (&bias)[M];
217 float x_scale;
218 float w_scale;
219 float y_scale;
220 TT x_zero;
221 TTPARAM w_zero;
222 TT y_zero;
223
224 // precomputation
225 int scalebits;
226 int16_t scale;
227
228 public:
230 TTPARAM (&w)[M*C*16],
231 int32_t (&b)[M],
232 float x_scale,
233 float w_scale,
234 float y_scale,
235 TT x_zero,
236 TTPARAM w_zero,
237 TT y_zero
238 );
239
240 void filter(
241 input_window<TT>* in,
242 output_window<TT>* out
243 );
244
245 static void registerKernelClass() {
246 static_assert((std::is_same<TT, int8_t>::value));
247 static_assert(KH==3);
248 static_assert(KW==3);
249 static_assert(GROUP == 1);
250 static_assert(INP_W%16==0);
251 static_assert(OUT_W_PAD%16==0);
252 REGISTER_FUNCTION(QLinearConv3x3::filter);
253 REGISTER_PARAMETER(weights);
254 REGISTER_PARAMETER(bias);
255 }
256};
257
258
265template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
267
268 private:
269 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
270 static constexpr int C_PER_M = C / GROUP;
271 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
272
273 alignas(32) int32_t (&bias)[M];
274 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
275 float x_scale;
276 float w_scale;
277 float y_scale;
278 TT x_zero;
279 TTPARAM w_zero;
280 TT y_zero;
281
282 float scale;
283
284 public:
286 int32_t (&b)[M],
287 float x_scale,
288 float w_scale,
289 float y_scale,
290 TT x_zero,
291 TTPARAM w_zero,
292 TT y_zero
293 ): bias(b), x_scale(x_scale), w_scale(w_scale), y_scale(y_scale), x_zero(x_zero), w_zero(w_zero), y_zero(y_zero) {
294 scale = x_scale*w_scale/y_scale;
295 };
296
297 void filter(
298 input_window<TT>* in,
299 input_stream<TTPARAM>* weights,
300 output_stream<TT>* out
301 );
302
303 static void registerKernelClass() {
304 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
305 REGISTER_FUNCTION(QLinearConvScalarStream::filter);
306 REGISTER_PARAMETER(bias);
307 }
308};
309
310
319template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
321
322 private:
323 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
324 static constexpr int C_PER_M = C / GROUP;
325 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
326
327 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
328 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
329
330 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
331 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
332 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
333
334 alignas(32) int32_t (&bias)[M];
335 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
336 float x_scale;
337 float w_scale;
338 float y_scale;
339 TT x_zero;
340 TTPARAM w_zero;
341 TT y_zero;
342
343 // precomputation
344 int scalebits;
345 int16_t scale;
346
347 public:
349 int32_t (&b)[M],
350 float x_scale,
351 float w_scale,
352 float y_scale,
353 TT x_zero,
354 TTPARAM w_zero,
355 TT y_zero
356 );
357
358 void filter(
359 input_window<TT>* in,
360 input_stream<TTPARAM>* weights,
361 output_stream<TT>* out
362 );
363
364 static void registerKernelClass() {
365 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
366 static_assert(KW<=4);
367 static_assert(INP_W%16==0);
368 static_assert(OUT_W_PAD%16==0);
369 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
370 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
371 REGISTER_FUNCTION(QLinearConvHx4Stream::filter);
372 REGISTER_PARAMETER(bias);
373 }
374};
375
376
385template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
387
388 private:
389 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
390 static constexpr int C_PER_M = C / GROUP;
391 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
392
393 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
394 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
395
396 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
397 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
398 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
399
400 alignas(32) int32_t (&bias)[M];
401 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
402 float x_scale;
403 float w_scale;
404 float y_scale;
405 TT x_zero;
406 TTPARAM w_zero;
407 TT y_zero;
408
409 // precomputation
410 int scalebits;
411 int32_t scale;
412
413 public:
415 int32_t (&b)[M],
416 float x_scale,
417 float w_scale,
418 float y_scale,
419 TT x_zero,
420 TTPARAM w_zero,
421 TT y_zero
422 );
423
424 void filter(
425 input_window<TT>* in,
426 input_stream<TTPARAM>* weights,
427 output_stream<TT>* out
428 );
429
430 static void registerKernelClass() {
431 static_assert((std::is_same<TT, int8_t>::value));
432 static_assert(KW<=4);
433 static_assert(INP_W%16==0);
434 static_assert(OUT_W_PAD%16==0);
435 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
436 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
437 REGISTER_FUNCTION(QLinearConvHx4StreamScale32bit::filter);
438 REGISTER_PARAMETER(bias);
439 }
440};
441
442
449template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
451
452 private:
453 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
454 static constexpr int C_PER_M = C / GROUP;
455 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
456 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
457
458 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
459 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
460
461 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
462 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
463 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
464
465 alignas(32) int32_t (&bias)[M];
466 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
467 alignas(32) TT in[INP_SIZE];
468 float x_scale;
469 float w_scale;
470 float y_scale;
471 TT x_zero;
472 TTPARAM w_zero;
473 TT y_zero;
474
475 // precomputation
476 int scalebits;
477 int16_t scale;
478
479 public:
481 int32_t (&b)[M],
482 float x_scale,
483 float w_scale,
484 float y_scale,
485 TT x_zero,
486 TTPARAM w_zero,
487 TT y_zero
488 );
489
490 void filter(
491 input_pktstream* in_s,
492 input_stream<TTPARAM>* weights,
493 output_stream<TT>* out
494 );
495
496 static void registerKernelClass() {
497 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
498 static_assert(KW<=4);
499 static_assert(INP_W%16==0);
500 static_assert(OUT_W_PAD%16==0);
501 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
502 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
503 REGISTER_FUNCTION(QLinearConvHx4PktStream::filter);
504 REGISTER_PARAMETER(bias);
505 }
506};
507
508
509template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
510class QLinearConvHx4_0 {
511
512 private:
513 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
514 static constexpr int C_PER_M = C / GROUP;
515 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
516
517 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
518 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
519
520 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
521 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
522 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
523
524 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
525 alignas(32) int32_t (&bias)[M];
526 TTPARAM w_zero;
527
528 public:
529 QLinearConvHx4_0 (
530 TTPARAM (&w)[M*CKK_ROW_SIZE],
531 int32_t (&b)[M],
532 TTPARAM w_zero
533 ): weights(w), bias(b), w_zero(w_zero) {}
534
535 void filter(
536 input_window<TT>* in,
537 output_stream<acc48>* cout
538 );
539
540 static void registerKernelClass() {
541 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
542 static_assert(KW<=4);
543 static_assert(INP_W%16==0);
544 static_assert(OUT_W_PAD%16==0);
545 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
546 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
547 REGISTER_FUNCTION(QLinearConvHx4_0::filter);
548 REGISTER_PARAMETER(weights);
549 REGISTER_PARAMETER(bias);
550 }
551};
552
553
554template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
555class QLinearConvHx4_1 {
556
557 private:
558 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
559 static constexpr int C_PER_M = C / GROUP;
560 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
561
562 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
563 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
564
565 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
566 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
567 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
568
569 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
570 TTPARAM w_zero;
571
572 public:
573 QLinearConvHx4_1 (
574 TTPARAM (&w)[M*CKK_ROW_SIZE],
575 TTPARAM w_zero
576 ): weights(w), w_zero(w_zero) {}
577
578 void filter(
579 input_window<TT>* in,
580 input_stream<acc48>* cin,
581 output_stream<acc48>* cout
582 );
583
584 static void registerKernelClass() {
585 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
586 static_assert(KW<=4);
587 static_assert(INP_W%16==0);
588 static_assert(OUT_W_PAD%16==0);
589 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
590 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
591 REGISTER_FUNCTION(QLinearConvHx4_1::filter);
592 REGISTER_PARAMETER(weights);
593 }
594};
595
596
597template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
598class QLinearConvHx4_2 {
599
600 private:
601 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
602 static constexpr int C_PER_M = C / GROUP;
603 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
604
605 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
606 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
607
608 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
609 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
610 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
611
612 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
613 float x_scale;
614 float w_scale;
615 float y_scale;
616 TT x_zero;
617 TTPARAM w_zero;
618 TT y_zero;
619
620 // precomputation
621 int scalebits;
622 int16_t scale;
623
624 public:
625 QLinearConvHx4_2 (
626 TTPARAM (&w)[M*CKK_ROW_SIZE],
627 float x_scale,
628 float w_scale,
629 float y_scale,
630 TT x_zero,
631 TTPARAM w_zero,
632 TT y_zero
633 );
634
635 void filter(
636 input_window<TT>* in,
637 input_stream<acc48>* cin,
638 output_stream<TT>* out
639 );
640
641 static void registerKernelClass() {
642 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
643 static_assert(KW<=4);
644 static_assert(INP_W%16==0);
645 static_assert(OUT_W_PAD%16==0);
646 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
647 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
648 REGISTER_FUNCTION(QLinearConvHx4_2::filter);
649 REGISTER_PARAMETER(weights);
650 }
651};
652
653
654template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
655class QLinearConvHx4Stream_0 {
656
657 private:
658 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
659 static constexpr int C_PER_M = C / GROUP;
660 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
661 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
662
663 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
664 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
665
666 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
667 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
668 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
669
670 alignas(32) int32_t (&bias)[M];
671 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
672 alignas(32) TT in[INP_SIZE];
673 float x_scale;
674 float w_scale;
675 float y_scale;
676 TT x_zero;
677 TTPARAM w_zero;
678 TT y_zero;
679
680 // precomputation
681 int scalebits;
682 int16_t scale;
683
684 public:
685 QLinearConvHx4Stream_0 (
686 int32_t (&b)[M],
687 TTPARAM w_zero
688 ): bias(b), w_zero(w_zero) {}
689
690 void filter(
691 input_pktstream* in_s,
692 input_stream<TTPARAM>* weights,
693 output_stream<acc48>* cout
694 );
695
696 static void registerKernelClass() {
697 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
698 static_assert(KW<=4);
699 static_assert(INP_W%16==0);
700 static_assert(OUT_W_PAD%16==0);
701 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
702 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
703 REGISTER_FUNCTION(QLinearConvHx4Stream_0::filter);
704 REGISTER_PARAMETER(bias);
705 }
706};
707
708
709template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
710class QLinearConvHx4Stream_1 {
711
712 private:
713 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
714 static constexpr int C_PER_M = C / GROUP;
715 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
716 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
717
718 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
719 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
720
721 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
722 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
723 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
724
725 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
726 alignas(32) TT in[INP_SIZE];
727 float x_scale;
728 float w_scale;
729 float y_scale;
730 TT x_zero;
731 TTPARAM w_zero;
732 TT y_zero;
733
734 // precomputation
735 int scalebits;
736 int16_t scale;
737
738 public:
739 QLinearConvHx4Stream_1 (
740 TTPARAM w_zero
741 ): w_zero(w_zero) {}
742
743 void filter(
744 input_pktstream* in_s,
745 input_stream<TTPARAM>* weights,
746 input_stream<acc48>* cin,
747 output_stream<acc48>* cout
748 );
749
750 static void registerKernelClass() {
751 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
752 static_assert(KW<=4);
753 static_assert(INP_W%16==0);
754 static_assert(OUT_W_PAD%16==0);
755 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
756 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
757 REGISTER_FUNCTION(QLinearConvHx4Stream_1::filter);
758 }
759};
760
761
762template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
763class QLinearConvHx4Stream_2 {
764
765 private:
766 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
767 static constexpr int C_PER_M = C / GROUP;
768 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
769 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
770
771 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : ((STEP_W == 2) ? 0x76543210 : 0xeca86420);
772 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
773
774 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
775 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
776 static constexpr int W_LOOP_IN_STEP = (STEP_W != 4) ? 16 : 32;
777
778 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
779 alignas(32) TT in[INP_SIZE];
780 float x_scale;
781 float w_scale;
782 float y_scale;
783 TT x_zero;
784 TTPARAM w_zero;
785 TT y_zero;
786
787 // precomputation
788 int scalebits;
789 int16_t scale;
790
791 public:
792 QLinearConvHx4Stream_2 (
793 float x_scale,
794 float w_scale,
795 float y_scale,
796 TT x_zero,
797 TTPARAM w_zero,
798 TT y_zero
799 );
800
801 void filter(
802 input_pktstream* in_s,
803 input_stream<TTPARAM>* weights,
804 input_stream<acc48>* cin,
805 output_stream<TT>* out
806 );
807
808 static void registerKernelClass() {
809 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
810 static_assert(KW<=4);
811 static_assert(INP_W%16==0);
812 static_assert(OUT_W_PAD%16==0);
813 static_assert(STEP_H == 1 || STEP_H == 2 || STEP_H == 4);
814 static_assert(STEP_W == 1 || STEP_W == 2 || STEP_W == 4);
815 REGISTER_FUNCTION(QLinearConvHx4Stream_2::filter);
816 }
817};
818
819
827template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
829
830 private:
831 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
832 static constexpr int C_PER_M = C / GROUP;
833 static constexpr int CKK_ROW_SIZE = C_PER_M*KH*16;
834
835 alignas(32) int32_t (&bias)[M];
836 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
837 float x_scale;
838 float w_scale;
839 float y_scale;
840 TT x_zero;
841 TTPARAM w_zero;
842 TT y_zero;
843
844 // precomputation
845 int scalebits;
846 int16_t scale;
847
848 public:
850 int32_t (&b)[M],
851 float x_scale,
852 float w_scale,
853 float y_scale,
854 TT x_zero,
855 TTPARAM w_zero,
856 TT y_zero
857 );
858
859 void filter(
860 input_window<TT>* in,
861 input_stream<TTPARAM>* weights,
862 output_stream<TT>* out
863 );
864
865 static void registerKernelClass() {
866 static_assert((std::is_same<TT, int8_t>::value));
867 static_assert(KW<=6);
868 static_assert(INP_W%16==0);
869 static_assert(OUT_W_PAD%16==0);
870 static_assert(STEP_H == 1);
871 static_assert(STEP_W == 1);
872 REGISTER_FUNCTION(QLinearConvHx6x8bitStream::filter);
873 REGISTER_PARAMETER(bias);
874 }
875};
876
877
883template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
885
886 private:
887 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
888 static constexpr int C_PER_M = C / GROUP;
889 static constexpr int CKK_ROW_SIZE = C_PER_M*((KH*KW+15)/16*16);
890
891 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : 0x76543210;
892 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
893
894 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
895 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
896
897 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
898 alignas(32) int32_t (&bias)[M];
899 float x_scale;
900 float w_scale;
901 float y_scale;
902 TT x_zero;
903 TTPARAM w_zero;
904 TT y_zero;
905
906 // precomputation
907 int scalebits;
908 int16_t scale;
909
910 public:
912 TTPARAM (&w)[M*CKK_ROW_SIZE],
913 int32_t (&b)[M],
914 float x_scale,
915 float w_scale,
916 float y_scale,
917 TT x_zero,
918 TTPARAM w_zero,
919 TT y_zero
920 );
921
922 void filter(
923 input_window<TT>* in,
924 output_stream<TT>* out
925 );
926
927 static void registerKernelClass() {
928 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
929 static_assert(KW<=8);
930 static_assert(INP_W%16==0);
931 static_assert(OUT_W_PAD%16==0);
932 static_assert(STEP_H == 1 || STEP_H == 2);
933 static_assert(STEP_W == 1 || STEP_W == 2);
934 REGISTER_FUNCTION(QLinearConvHx8::filter);
935 REGISTER_PARAMETER(weights);
936 REGISTER_PARAMETER(bias);
937 }
938};
939
940
946template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
948
949 private:
950 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
951 static constexpr int CKK_ROW_SIZE = C*((KH*KW+15)/16*16);
952 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
953
954 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : 0x76543210;
955 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x2110 : 0x3210;
956
957 // v32 data limits strides 2, 4 to compute 8 values, note KW <= 4
958 static constexpr int W_LOOP_STEP = (STEP_W == 1) ? 16 : 8;
959
960 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
961 alignas(32) int32_t (&bias)[M];
962 float x_scale;
963 float w_scale;
964 float y_scale;
965 TT x_zero;
966 TTPARAM w_zero;
967 TT y_zero;
968 alignas(32) TT in[INP_SIZE];
969
970 // precomputation
971 int scalebits;
972 int16_t scale;
973
974 public:
976 TTPARAM (&w)[M*CKK_ROW_SIZE],
977 int32_t (&b)[M],
978 float x_scale,
979 float w_scale,
980 float y_scale,
981 TT x_zero,
982 TTPARAM w_zero,
983 TT y_zero
984 );
985
986 void filter(
987 input_pktstream* in,
988 output_stream<TT>* out
989 );
990
991 static void registerKernelClass() {
992 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
993 static_assert(KW<=8);
994 static_assert(INP_W%16==0);
995 static_assert(OUT_W_PAD%16==0);
996 static_assert(STEP_H == 1 || STEP_H == 2);
997 static_assert(STEP_W == 1 || STEP_W == 2);
998 static_assert(GROUP == 1);
999 REGISTER_FUNCTION(QLinearConvHx8PktStream::filter);
1000 REGISTER_PARAMETER(weights);
1001 REGISTER_PARAMETER(bias);
1002 }
1003};
1004
1005
1014template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1016
1017 private:
1018 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1019 static constexpr int C_PER_M = C / GROUP;
1020 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1021 static constexpr int LAST_C = (C_PER_M % 16 - 1) /2*2;
1022
1023 static constexpr unsigned int MAC_ZOFFSET = (STEP_W == 1) ? 0x43322110 : 0x76543210;
1024 static constexpr unsigned int MAC_ZSQUARE = (STEP_W == 1) ? 0x3120 : 0x3210;
1025
1026 alignas(32) int32_t (&bias)[M];
1027 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
1028 float x_scale;
1029 float w_scale;
1030 float y_scale;
1031 TT x_zero;
1032 TTPARAM w_zero;
1033 TT y_zero;
1034
1035 // precomputation
1036 int scalebits;
1037 int16_t scale;
1038
1039 public:
1041 int32_t (&b)[M],
1042 float x_scale,
1043 float w_scale,
1044 float y_scale,
1045 TT x_zero,
1046 TTPARAM w_zero,
1047 TT y_zero
1048 );
1049
1050 void filter(
1051 input_window<TT>* in,
1052 input_stream<TTPARAM>* weights,
1053 output_stream<TT>* out
1054 );
1055
1056 static void registerKernelClass() {
1057 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1058 static_assert(KH==1);
1059 static_assert(KW==1);
1060 static_assert(INP_W%16==0);
1061 static_assert(OUT_W_PAD%16==0);
1062 static_assert(STEP_H == 1 || STEP_H == 2);
1063 static_assert(STEP_W == 1 || STEP_W == 2);
1064 REGISTER_FUNCTION(QLinearConv1x1Stream::filter);
1065 REGISTER_PARAMETER(bias);
1066 }
1067};
1068
1069
1076template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1078
1079 private:
1080 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1081 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
1082 static constexpr int C_PER_M = C / GROUP;
1083 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1084 static constexpr int LAST_C = (C_PER_M % 16 - 1) /2*2;
1085
1086 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
1087 alignas(32) int32_t (&bias)[M];
1088 alignas(32) TT in[INP_SIZE];
1089
1090 float x_scale;
1091 float w_scale;
1092 float y_scale;
1093 TT x_zero;
1094 TTPARAM w_zero;
1095 TT y_zero;
1096
1097 // precomputation
1098 int scalebits;
1099 int16_t scale;
1100
1101 public:
1103 TTPARAM (&w)[M*CKK_ROW_SIZE],
1104 int32_t (&b)[M],
1105 float x_scale,
1106 float w_scale,
1107 float y_scale,
1108 TT x_zero,
1109 TTPARAM w_zero,
1110 TT y_zero
1111 );
1112
1113 void filter(
1114 input_pktstream* in_s,
1115 output_stream<TT>* out
1116 );
1117
1118 static void registerKernelClass() {
1119 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1120 static_assert(KH==1);
1121 static_assert(KW==1);
1122 static_assert(INP_W%16==0);
1123 static_assert(OUT_W_PAD%16==0);
1124 static_assert(STEP_H == 1 || STEP_H == 2);
1125 static_assert(STEP_W == 1 || STEP_W == 2);
1126 REGISTER_FUNCTION(QLinearConv1x1InputPackets::filter);
1127 REGISTER_PARAMETER(weights);
1128 REGISTER_PARAMETER(bias);
1129 }
1130};
1131
1132
1139template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1141
1142 private:
1143 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1144 static constexpr int INP_SIZE = B*C*INP_H*INP_W;
1145 static constexpr int C_PER_M = C / GROUP;
1146 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1147 static constexpr int LAST_C = (C_PER_M % 16 - 1) /2*2;
1148
1149 alignas(32) int32_t (&bias)[M];
1150 alignas(32) TTPARAM ckk_row[CKK_ROW_SIZE];
1151 alignas(32) TT in[INP_SIZE];
1152
1153 float x_scale;
1154 float w_scale;
1155 float y_scale;
1156 TT x_zero;
1157 TTPARAM w_zero;
1158 TT y_zero;
1159
1160 // precomputation
1161 int scalebits;
1162 int16_t scale;
1163
1164 public:
1166 int32_t (&b)[M],
1167 float x_scale,
1168 float w_scale,
1169 float y_scale,
1170 TT x_zero,
1171 TTPARAM w_zero,
1172 TT y_zero
1173 );
1174
1175 void filter(
1176 input_pktstream* in_s,
1177 input_stream<TTPARAM>* weights,
1178 output_stream<TT>* out
1179 );
1180
1181 static void registerKernelClass() {
1182 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1183 static_assert(KH==1);
1184 static_assert(KW==1);
1185 static_assert(INP_W%16==0);
1186 static_assert(OUT_W_PAD%16==0);
1187 static_assert(STEP_H == 1 || STEP_H == 2);
1188 static_assert(STEP_W == 1 || STEP_W == 2);
1189 REGISTER_FUNCTION(QLinearConv1x1StreamInputPackets::filter);
1190 REGISTER_PARAMETER(bias);
1191 }
1192};
1193
1194
1195template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1196class QLinearConv1x1_0 {
1197
1198 private:
1199 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1200 static constexpr int C_PER_M = C / GROUP;
1201 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1202 static constexpr int LAST_C = (C_PER_M % 16) / 2;
1203
1204 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
1205 alignas(32) int32_t (&bias)[M];
1206 TTPARAM w_zero;
1207
1208 public:
1209 QLinearConv1x1_0 (
1210 TTPARAM (&w)[M*CKK_ROW_SIZE],
1211 int32_t (&b)[M],
1212 TTPARAM w_zero
1213 ): weights(w), bias(b), w_zero(w_zero) {}
1214
1215 void filter(
1216 input_window<TT>* in,
1217 output_stream<acc48>* cout
1218 );
1219
1220 static void registerKernelClass() {
1221 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1222 static_assert(KH==1);
1223 static_assert(KW==1);
1224 static_assert(INP_W%16==0);
1225 static_assert(OUT_W_PAD%16==0);
1226 static_assert(STEP_H == 1 || STEP_H == 2);
1227 static_assert(STEP_W == 1 || STEP_W == 2);
1228 REGISTER_FUNCTION(QLinearConv1x1_0::filter);
1229 REGISTER_PARAMETER(weights);
1230 REGISTER_PARAMETER(bias);
1231 }
1232};
1233
1234
1235template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1236class QLinearConv1x1_1 {
1237
1238 private:
1239 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1240 static constexpr int C_PER_M = C / GROUP;
1241 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1242 static constexpr int LAST_C = (C_PER_M % 16) / 2;
1243
1244 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
1245 TTPARAM w_zero;
1246
1247 public:
1248 QLinearConv1x1_1 (
1249 TTPARAM (&w)[M*CKK_ROW_SIZE],
1250 TTPARAM w_zero
1251 ): weights(w), w_zero(w_zero) {}
1252
1253 void filter(
1254 input_window<TT>* in,
1255 input_stream<acc48>* cin,
1256 output_stream<acc48>* cout
1257 );
1258
1259 static void registerKernelClass() {
1260 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1261 static_assert(KH==1);
1262 static_assert(KW==1);
1263 static_assert(INP_W%16==0);
1264 static_assert(OUT_W_PAD%16==0);
1265 static_assert(STEP_H == 1 || STEP_H == 2);
1266 static_assert(STEP_W == 1 || STEP_W == 2);
1267 REGISTER_FUNCTION(QLinearConv1x1_1::filter);
1268 REGISTER_PARAMETER(weights);
1269 }
1270};
1271
1272
1273template <typename TT, typename TTPARAM, int INP_H, int INP_W, int OUT_W, int OUT_W_PAD, int STEP_H, int STEP_W, int B, int C, int M, int KH, int KW, int GROUP>
1274class QLinearConv1x1_2 {
1275
1276 private:
1277 static constexpr int OUT_H = (INP_H - KH) / STEP_H + 1;
1278 static constexpr int C_PER_M = C / GROUP;
1279 static constexpr int CKK_ROW_SIZE = (C_PER_M+15)/16*16;
1280 static constexpr int LAST_C = (C_PER_M % 16) / 2;
1281
1282 alignas(32) TTPARAM (&weights)[M*CKK_ROW_SIZE];
1283 float x_scale;
1284 float w_scale;
1285 float y_scale;
1286 TT x_zero;
1287 TTPARAM w_zero;
1288 TT y_zero;
1289
1290 // precomputation
1291 int scalebits;
1292 int16_t scale;
1293
1294 public:
1295 QLinearConv1x1_2 (
1296 TTPARAM (&w)[M*CKK_ROW_SIZE],
1297 float x_scale,
1298 float w_scale,
1299 float y_scale,
1300 TT x_zero,
1301 TTPARAM w_zero,
1302 TT y_zero
1303 );
1304
1305 void filter(
1306 input_window<TT>* in,
1307 input_stream<acc48>* cin,
1308 output_stream<TT>* out
1309 );
1310
1311 static void registerKernelClass() {
1312 static_assert((std::is_same<TT, int8_t>::value) || (std::is_same<TT, uint8_t>::value));
1313 static_assert(KH==1);
1314 static_assert(KW==1);
1315 static_assert(INP_W%16==0);
1316 static_assert(OUT_W_PAD%16==0);
1317 static_assert(STEP_H == 1 || STEP_H == 2);
1318 static_assert(STEP_W == 1 || STEP_W == 2);
1319 REGISTER_FUNCTION(QLinearConv1x1_2::filter);
1320 REGISTER_PARAMETER(weights);
1321 }
1322};
1326#endif // QLINEARCONV_H_
Vector implementation for 1x1 QLinearConv, stores weights requires data to be reshaped from (M,...
Definition qlinearconv.h:1077
Vector implementation for 1x1 QLinearConv, streams weights requires data to be reshaped from (M,...
Definition qlinearconv.h:1140
Vector implementation for 1x1 QLinearConv, requires data to be reshaped from (M,C,...
Definition qlinearconv.h:1015
Vector implementation for Hx4 QLinearConv, requires data to be arranged in [a,b,c,...
Definition qlinearconv.h:207
Vector implementation for Hx4 QLinearConv, requires data to be arranged in [a,b,c,...
Definition qlinearconv.h:153
Vector implementation for QLinearConv 5x5, requires data to be arranged in [a,b,c,...
Definition qlinearconv.h:96
void filter(input_window< TT > *in, output_window< TT > *out)
Definition qlinearconv.cc:134
Vector implementation for Hx4 QLinearConv, padding with y_zero, requires data to be arranged in (M,...
Definition qlinearconv.h:450
Vector implementation for Hx4 QLinearConv using 32bit scale for precision, requires data to be arrang...
Definition qlinearconv.h:386
Vector implementation for Hx4 QLinearConv, requires data to be arranged in [a,b,c,...
Definition qlinearconv.h:320
Vector implementation for Hx4 QLinearConv using int8xint8 MACs, requires data to be arranged in [a,...
Definition qlinearconv.h:828
Vector implementation for Hx8 QLinearConv, requires bias to be shifted, i.e. tbias - tw....
Definition qlinearconv.h:947
Vector implementation for Hx8 QLinearConv, requires bias to be shifted, i.e. tbias - tw....
Definition qlinearconv.h:884
Scalar implementation streaming weights, requires weights stream to be padded from MxCxKxK to MxCx16,...
Definition qlinearconv.h:266
Scalar implementation, QLinearConvScalar<30,32,28,32,1,1,1,1,6,5> total = 1282213,...
Definition qlinearconv.h:43