1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        Sched.h
4  * Description:  C++ support templates for the SDF scheduler
5  *
6  * $Date:        29 July 2021
7  * $Revision:    V1.10.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #ifndef _SCHEDGEN_H_
30 #define _SCHEDGEN_H_
31 
32 #include <vector>
33 
34 // FIFOS
35 
36 #ifdef DEBUGSCHED
37 
38 template<typename T>
39 struct debugtype{
40     typedef T type;
41 };
42 
43 template<>
44 struct debugtype<char>{
45     typedef int type;
46 };
47 
48 template<typename T>
49 using Debug = struct debugtype<T>;
50 
51 #endif
52 
53 template<typename T>
54 class FIFOBase{
55 public:
56     virtual T* getWriteBuffer(int nb)=0;
57     virtual T* getReadBuffer(int nb)=0;
58 };
59 
60 
61 template<typename T, int length, int isArray=0>
62 class FIFO: public FIFOBase<T>
63 {
64     public:
65         FIFO(T *buffer,int delay=0):mBuffer(buffer),readPos(0),writePos(delay) {};
66         FIFO(uint8_t *buffer,int delay=0):mBuffer((T*)buffer),readPos(0),writePos(delay) {};
67 
68         T * getWriteBuffer(int nb) override
69         {
70             if (isArray==1)
71             {
72                 return(mBuffer);
73             }
74 
75             T *ret;
76             if (readPos > 0)
77             {
78                 memcpy((void*)mBuffer,(void*)(mBuffer+readPos),(writePos-readPos)*sizeof(T));
79                 writePos -= readPos;
80                 readPos = 0;
81             }
82 
83             ret = mBuffer + writePos;
84             writePos += nb;
85             return(ret);
86         };
87 
88         T* getReadBuffer(int nb) override
89         {
90             if (isArray==1)
91             {
92                 return(mBuffer);
93             }
94 
95             T *ret = mBuffer + readPos;
96             readPos += nb;
97             return(ret);
98         }
99 
100         #ifdef DEBUGSCHED
101         void dump()
102         {
103             int nb=0;
104             std::cout << std::endl;
105             for(int i=0; i < length ; i++)
106             {
107                 std::cout << (Debug<T>::type)mBuffer[i] << " ";
108                 nb++;
109                 if (nb == 10)
110                 {
111                     nb=0;
112                     std::cout << std::endl;
113                 }
114             }
115             std::cout << std::endl;
116             std::cout << std::endl;
117         }
118         #endif
119 
120     protected:
121         T *mBuffer;
122         int readPos,writePos;
123 };
124 
125 // GENERIC NODES
126 
127 class NodeBase
128 {
129 public:
130     virtual int run()=0;
131 };
132 
133 template<typename IN, int inputSize,typename OUT, int outputSize>
134 class GenericNode:public NodeBase
135 {
136 public:
137      GenericNode(FIFOBase<IN> &src,FIFOBase<OUT> &dst):mSrc(src),mDst(dst){};
138 
139 protected:
140      OUT * getWriteBuffer(){return mDst.getWriteBuffer(outputSize);};
141      IN * getReadBuffer(){return mSrc.getReadBuffer(inputSize);};
142 
143 private:
144     FIFOBase<IN> &mSrc;
145     FIFOBase<OUT> &mDst;
146 };
147 
148 template<typename IN, int inputSize,typename OUT1, int output1Size,typename OUT2, int output2Size>
149 class GenericNode12:public NodeBase
150 {
151 public:
152      GenericNode12(FIFOBase<IN> &src,FIFOBase<OUT1> &dst1,FIFOBase<OUT2> &dst2):mSrc(src),
153      mDst1(dst1),mDst2(dst2){};
154 
155 protected:
156      OUT1 * getWriteBuffer1(){return mDst1.getWriteBuffer(output1Size);};
157      OUT2 * getWriteBuffer2(){return mDst2.getWriteBuffer(output2Size);};
158      IN * getReadBuffer(){return mSrc.getReadBuffer(inputSize);};
159 
160 private:
161     FIFOBase<IN> &mSrc;
162     FIFOBase<OUT1> &mDst1;
163     FIFOBase<OUT2> &mDst2;
164 };
165 
166 template<typename IN1, int input1Size,typename IN2, int input2Size,typename OUT, int outputSize>
167 class GenericNode21:public NodeBase
168 {
169 public:
170      GenericNode21(FIFOBase<IN1> &src1,FIFOBase<IN2> &src2,FIFOBase<OUT> &dst):mSrc1(src1),
171      mSrc2(src2),
172      mDst(dst){};
173 
174 protected:
175      OUT * getWriteBuffer(){return mDst.getWriteBuffer(outputSize);};
176      IN1 * getReadBuffer1(){return mSrc1.getReadBuffer(input1Size);};
177      IN2 * getReadBuffer2(){return mSrc2.getReadBuffer(input2Size);};
178 
179 private:
180     FIFOBase<IN1> &mSrc1;
181     FIFOBase<IN2> &mSrc2;
182     FIFOBase<OUT> &mDst;
183 };
184 
185 
186 
187 template<typename OUT, int outputSize>
188 class GenericSource:public NodeBase
189 {
190 public:
191      GenericSource(FIFOBase<OUT> &dst):mDst(dst){};
192 
193 protected:
194      OUT * getWriteBuffer(){return mDst.getWriteBuffer(outputSize);};
195 
196 private:
197     FIFOBase<OUT> &mDst;
198 };
199 
200 template<typename IN,int inputSize>
201 class GenericSink:public NodeBase
202 {
203 public:
204      GenericSink(FIFOBase<IN> &src):mSrc(src){};
205 
206 protected:
207      IN * getReadBuffer(){return mSrc.getReadBuffer(inputSize);};
208 
209 private:
210     FIFOBase<IN> &mSrc;
211 };
212 
213 
214 #define REPEAT(N) for(int i=0;i<N;i++)
215 
216 // GENERIC APPLICATION NODES
217 
218 template<typename IN,int windowSize, int overlap>
219 class SlidingBuffer: public GenericNode<IN,windowSize-overlap,IN,windowSize>
220 {
221 public:
222     SlidingBuffer(FIFOBase<IN> &src,FIFOBase<IN> &dst):GenericNode<IN,windowSize-overlap,IN,windowSize>(src,dst)
223     {
224         static_assert((windowSize-overlap)>0, "Overlap is too big");
225         memory.resize(overlap);
226     };
227 
228     int run(){
229         IN *a=this->getReadBuffer();
230         IN *b=this->getWriteBuffer();
231         memcpy((void*)b,(void*)memory.data(),overlap*sizeof(IN));
232         memcpy((void*)(b+overlap),(void*)a,(windowSize-overlap)*sizeof(IN));
233         memcpy((void*)memory.data(),(void*)(b+windowSize-overlap),overlap*sizeof(IN)) ;
234         return(0);
235     };
236 protected:
237     std::vector<IN> memory;
238 
239 };
240 
241 template<typename IN,int windowSize, int overlap>
242 class OverlapAdd: public GenericNode<IN,windowSize,IN,windowSize-overlap>
243 {
244 public:
245     OverlapAdd(FIFOBase<IN> &src,FIFOBase<IN> &dst):GenericNode<IN,windowSize,IN,overlap>(src,dst)
246     {
247         static_assert((windowSize-overlap)>0, "Overlap is too big");
248         memory.resize(overlap);
249     };
250 
251     int run(){
252         int i;
253         IN *a=this->getReadBuffer();
254         IN *b=this->getWriteBuffer();
255 
256         for(i=0;i<overlap;i++)
257         {
258             memory[i] = a[i] + memory[i];
259         }
260 
261         if (2*overlap - windowSize > 0)
262         {
263 
264             memcpy((void*)b,(void*)memory.data(),(windowSize-overlap)*sizeof(IN));
265 
266             memmove(memory.data(),memory.data()+windowSize-overlap,(2*overlap - windowSize)*sizeof(IN));
267             memcpy(memory.data()+2*overlap - windowSize,a+overlap,(windowSize-overlap)*sizeof(IN));
268         }
269         else if (2*overlap - windowSize < 0)
270         {
271             memcpy((void*)b,(void*)memory.data(),overlap*sizeof(IN));
272             memcpy((void*)(b+overlap),(void*)(a+overlap),(windowSize - 2*overlap)*sizeof(IN));
273 
274             memcpy((void*)memory.data(),(void*)(a+windowSize-overlap),overlap*sizeof(IN));
275         }
276         else
277         {
278             memcpy((void*)b,(void*)memory.data(),overlap*sizeof(IN));
279 
280             memcpy((void*)memory.data(),(void*)(a+overlap),overlap*sizeof(IN));
281         }
282 
283         return(0);
284     };
285 protected:
286     std::vector<IN> memory;
287 
288 };
289 
290 #if !defined(CHECKERROR)
291 #define CHECKERROR       if (sdfError < 0) \
292        {\
293          break;\
294        }
295 
296 #endif
297 #endif
298