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